コルネの進捗や備忘録が記されたなにか

進捗や成果物や備忘録てきななにかを雑に更新していきます。

テキストに合わせてPower Apps のラベルの幅を変更させる


スポンサードリンク

はじめに

Power Apps のラベルには AutoHeight プロパティが存在し、このプロパティを true に設定するとテキストのサイズによってラベルの高さを自動調整してくれます。

docs.microsoft.com

AutoHeight – ラベルにすべてのテキストが表示されるように高さを自動的に調整する場合は true に設定します。 割り当てた高さでテキストを一部削除する場合は false に設定します。

ただし、テキストによってラベルの幅を自動で調整してくれるようなプロパティは存在しません。

ということでなければ作っちゃいましょう!

ラベルの幅を可変にするための仕組み

テキストの長さを計算する

ラベルに設定されたテキストの長さを計算します。
テキストの長さは Len 関数 で測ることができます。

ただし、これは全角 / 半角までは判定してくれず、あくまでテキストの文字数しか測ることができません。

f:id:koruneko:20211029000942p:plain

f:id:koruneko:20211029001143p:plain

このように、全角でも半角でも同じ5文字なので5を返します。

しかし、全角文字と半角文字とでは必要なテキストの描画領域は異なります。

f:id:koruneko:20211029001116p:plain

よって、全角と半角とで分けてカウントする仕組みが必要です。

これをずばり実現するようなPower Apps の関数は存在しないので、関数をいくつか組み合わせることで実現したいと思います。

全角と半角の判定には正規表現による判定を用います。
正規表現の抜出には MatchAll 関数 を用います。
これの結果はテーブルで返ってきますので、正規表現の結果何文字ヒットしたか?はそのテーブルの数をカウントしてあげればよいので CountRws 関数 を用います。

予め記載しておくと正規表現の詳しい解説は今回省きます。
簡単にいうと文字コードを用いて判定しています。

まず半角文字のカウントには以下の式を用います。

// 半角英数字・記号
CountRows(MatchAll(Label.Text, "[\x21-\x7eE]"))

全角文字(平仮名やカタカナ、漢字など)の判定には以下を用います。

// 全角文字
 CountRows(MatchAll(Label.Text, "[^\x01-\x7E\xA1-\xDF]"))

ただし、これでは全角記号が漏れてしまいますので、以下で全角記号も網羅します。

// 全角記号
CountRows(MatchAll(Label.Text, "[/[!-/:-@[-`{-~、-〜”’・]+/g]"))

これらの式を使って、テキストに設定された全角と半角のカウントを行った式が以下になります。

f:id:koruneko:20211029001735p:plain

ちゃんとカウントされてますね。

幅をテキストに合わせて変更する

全角と半角をわけてテキスト内の文字列をカウントできるようになりましたので、次はこれの結果をもとにラベルの幅を計算したいと思います。

簡単のため、全角文字は半角文字の2倍のサイズが必要として計算します。

(
    // 半角英数字・記号
    CountRows(MatchAll(Self.Text, "[\x21-\x7eE]")) +
    // 全角文字
    CountRows(MatchAll(Self.Text, "[^\x01-\x7E\xA1-\xDF]")) * 2 +
    // 全角記号
    CountRows(MatchAll(Self.Text, "[/[!-/:-@[-`{-~、-〜”’・]+/g]")) * 2
)

ラベルのパディング分だけ最低でも幅を取ってあげる必要があります。

Self.PaddingLeft + Self.PaddingRight

また、ラベルが画面のサイズを超えないようにも制御してあげます。

Parent.Width - Self.X

これらの要件を満たすように式を作成すると以下のようになりますね。

Label.Widh

Min(
    // 最大表示可能領域
    Parent.Width - Self.X,
    // 文字のサイズによって表示領域を可変にする
    Self.PaddingLeft + Self.PaddingRight +
    (
        // 半角英数字・記号
        CountRows(MatchAll(Self.Text, "[\x21-\x7eE]")) +
        // 全角文字
        CountRows(MatchAll(Self.Text, "[^\x01-\x7E\xA1-\xDF]")) * 2 +
        // 全角記号
        CountRows(MatchAll(Self.Text, "[/[!-/:-@[-`{-~、-〜”’・]+/g]")) * 2
    ) * Self.Size
)

これの結果のスクショをサンプルでここに貼り付けておきます。

なにもなし
f:id:koruneko:20211029005746p:plain

abcdefg
f:id:koruneko:20211029005734p:plain

あいうえお
f:id:koruneko:20211029005855p:plain

aあbいcうdえeお
f:id:koruneko:20211029005952p:plain

テキストのサイズに合わせてラベルの幅が可変になっていますね。

さらにもうワンステップ

迷走

この章は私の迷走の過程をメモとして記載しているだけなので、読み飛ばしても大丈夫です。

さて、先ほどの式でもラベルの幅を可変にすることはできましたが、テキストの量が増えれば増える程無駄な余白が増えてしまいました。

どうやら先ほどの式では少し不十分のようですね。
ということで式を改良します。
といっても闇雲に式を適応していくのも非効率ですので身近にある、テキストによってサイズの変わるコントロールの設定値を参考にします。

そこでパッと思い浮かんだのがPowerPoint のテキストボックスです。
あれは、テキストによってテキストボックスのサイズが可変になってくれますね。

まず、なにもテキストを設定しなかった場合は幅0.51 cm でした。

f:id:koruneko:20211029011734p:plain

次に半角1文字設定したときは0.77 cm でした

f:id:koruneko:20211029011726p:plain

といった感じで地道ですが、n 文字のとき X cm になるというデータを取得して計算式を割り出していきます。

需要あるか不明ですが、半角で計測したときの値は以下のようになりました。

文字数
0 0.51
1 0.77
2 1.06
3 1.28
4 1.54
5 1.80
6 2.05
7 2.31
8 2.57
9 2.83
10 3.09
11 3.35
12 3.60
13 3.86
14 4.12
15 4.38
16 4.64
17 4.90
18 5.15
19 5.41
20 5.67

この値の近似式を求めると以下になりました。

 y = 0.2577x + 0.513

なお多項式とした場合は

 y = 7 * 10^{-5}x^{2} + 0.2562x + 0.5176

となり、2次の値が充分小さい値であるので線形近似で今回は計算します。

このことからテキストサイズに比例した幅がPowerPoint では与えられているようですが、これをPower Apps にままあてはめてしまうとテキストサイズが増えてくるに従って余白も増えてしまうので、これは参考にできないですね。。。

色々試した結果

色々実際に値を入れたりとめんどくさい確認をした結果以下のような式がなんかいい感じになりました。

Label.Width

Min(
    // 最大表示可能領域
    Parent.Width - Self.X,
    // 文字のサイズによって表示領域を可変にする
    Self.PaddingLeft + Self.PaddingRight +
    With(
        {
            textCount:
                // 半角英数字・記号
                CountRows(MatchAll(Self.Text, "[\x20-\x7eE]")) +
                // 全角文字
                CountRows(MatchAll(Self.Text, "[^\x01-\x7E\xA1-\xDF]")) * 1.8 +
                // 全角記号
                CountRows(MatchAll(Self.Text, "[/[!-/:-@[-`{-~、-〜”’・]+/g]")) * 1.8
        },
        textCount * Self.Size * 0.75
    )
)

おわりに

なんかいい感じの式見つけられたけど、もっといい方法ないかなぁ。。。
なにかいい方法思いついたらまた更新します。

もし何かいいアイディアあれば教えていただけると幸いですー

追記

2021/10/29 追記
上記で紹介した方法でなんとなく幅をテキストにあわせて可変にする。は実現できましたが、もっと厳密に定義しようとするとこれだけでは足りません。

例えば同じ半角でも以下文字たちは必要な幅が異なります。
i
w
&
,
厳密に定義したいのであれば、なにかの文字を基準とし、その文字との幅の比率を定義したデータが必要になってくるかと思います。
それもフォント毎に異なるので、これだけのためにそのデータを用意して幅の自動調整を厳密に行う必要があるのか?は良く考えてから実施してください。


スポンサードリンク