- ベストアンサー
ExcelのVBAで高さの設定ができない問題について
- 報告書のフォーマットの作成をしている際に、コメントの文字数に応じて行の高さを変更するVBAを作成しました。しかし、特定の条件下で高さの設定が正しく行われない問題が発生しています。
- VBAの記述に間違いがあるようで、文字数が72文字以内の場合は高さを80に変更し、73文字以上で108文字未満の場合は高さを120に変更することが意図されていますが、108文字以上の場合でも高さが120になってしまう問題があります。
- この問題の解決方法について教えていただきたいです。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
VBの式の書き方がまずいです。 数学的記述ですと a < X < b という書き方は普通なのですが、プログラムでの式の評価はその書いている内容全てで1つの式とみなされ、数学で言うAより大きくBより小さいという2つの意味と理解してくれません。 ではこの時になぜ全て120になってしまうのかというと、VBの式は優先順位(カッコの中や掛け算は先に計算する)などが無い場合は左から順番に計算します。 この式がはじめに出てくるのは ElseIf 73 < Cells(i, 6) < 108 Then です。この式を解釈するにあたって、まずはVBは 73 < Cells(i, 6) を計算しに行きます。この時点では文字数が73より大きいという内容なので意図する動作ですね。 問題はここからです。 VBは四則演算などはそのまま計算した結果を覚えているのですが、大小比較等の場合はTrue(-1)かFalse(0)でしか結果を覚えません。例えば個々の例であえてこの条件式に当てはまらない200文字と仮定して解いて行きましょう。200と73だと200のほうが大きいので結果はTrue(-1)です。 そうするとVBは式の次の部分の評価を行います。ここがポイントです。 73 < 200 < 108 が1段階計算されると True < 108 という風に変わってしまうのです。 Trueは-1ですので実は文字が何文字入ろうが関係なくこの式はTrueになってしまうのです。 全部の計算結果がTrueなので、文字数が72文字以降は全て高さが120になってしまうのがこの不具合の原因です。 こういう時の解決策は2つあります。 1個目はIfの条件式を正しく書きなおしてください。Ifで複数条件を書く場合は、And Or Xorなどで結合します。「vb 論理演算子」のあたりで調べてみるといいでしょう。 2個目は、Select Caseを用いると今の書き方に近い記述が可能です。 Select Case cells(i, 6) Case Is <72 Rows(i).RowHeight = 80 Case 73 to 108 Rows(i).RowHeight = 120 Case 109 to 114 Rows(i).RowHeight = 160 [中略] Case Else その他の場合をここに記述 End Select このような感じです。 ここからは余談ですが、幾つかアドバイスする部分があります。重要なものから順に 1.このプログラムでは処理が漏れるパターンが存在します。 この条件式では文字数が72,73,108,109,144,145,180,181,216,217,252,253,288,289文字の場合にセルの高さを変える処理が漏れてしまいます。以上以下を使いたい場合は「<や>」から「<=や>=」を用いて見てください。(実際はそれぞれを上手く組み合わせて使用します) 2.VB付属のLen関数も使用可能です。 現在は、6列目に何文字あったかをExcelのLen関数で書き込んでいると思うのですが、Len関数はVBにも存在します。例えば4列目に文字数を調べたい文字が入っているとしたら MojiCount = Len(Cells(i, 4).Value)) と書くことで、Excelに作業列を作成することなく文字数による条件判断が可能になります。 もちろんその後の処理は If MojiCount < 72 Then・・・ のように記述するだけです。余力があればお試しください。 ※注意 If MojiCount < Len(Cells(i, 4).Value)) Then 反復して何度も記述する部分にこのように記述するのは可読性低下と微量ながら処理速度の低減につながるのでお勧めしません。 その場合はSelect Case Len(Cells(i, 4).Value)とSelect Caseで記述するのが好ましいです。 3.プロパティーを明示しましょう。 規定プロパティーというのですが、Cells(i, 6)のみだと自動的にValueプロパティーが指定されます。そのままでも動作はするのですが、今後のことを考えるのであればバグ回避の練習などの意味合いも含めてCells(i, 6).Valueなどと明示するようにしましょう。 以上、長文になりましたが、今後のステップアップの糧になれば幸いです。
その他の回答 (4)
- mu2011
- ベストアンサー率38% (1910/4994)
>ElseIf 73 < Cells(i, 6) < 108 Then ⇒このコードでは、後続の比較は無視され、先頭の比較のみになりますのでそのような振る舞いになりますので、前方の比較を削除すればよいと思います。 一例ですが、このような振分けIfよりselect caseが分かり易いので次のコードは如何でしょうか。 又、行範囲の可変扱い、元データG列は不要と思いますので少しアレンジしてみました。 Sub Macro1() For i = 2 To Cells(Rows.Count,"F").End(Xlup).Row Select Case Len(Cells(i, "F")) Case 0 To 71: rowh = 80 Case 72 To 107: rowh = 120 ~以下同様~ Case 288 To 323: rowh = 360 End Select Rows(i).RowHeight = rowh Next End Sub
お礼
mu2011様 >又、行範囲の可変扱い、元データG列は不要と思いますので少しアレンジしてみました。 LEN関数を組み込んだVBA、ありがとうございます。 初めてのVBAの為、知らない言葉(Xlup等)が多いですが、勉強になります。 mu2011さんのVBAを使わせて頂きます。
- imogasi
- ベストアンサー率27% (4737/17069)
エクセルの操作で、書式ーセルー配置に 「折り返して全体を表示する」が在る。 範囲指定して(多数セルに一遍で)VBAのコードでもプログラムから設置できる。 これではダメなのか? これで良いなら、VBAを云々する前に、エクセルの基本機能を勉強すること。そうしないと簡単に出来ることを、我流のプログラムで(往々にして、回りくどく、エラーが潜在する)してしまうことになる。
お礼
imogasi様 >「折り返して全体を表示する」が在る。 >範囲指定して(多数セルに一遍で)VBAのコードでもプログラムから設置できる。 >これではダメなのか? >これで良いなら、VBAを云々する前に、エクセルの基本機能を勉強すること。そうしないと簡単に >出来ることを、我流のプログラムで(往々にして、回りくどく、エラーが潜在する)してしまうこと >になる。 ありがとうございます。 今回は、「報告書」形式の為、コメント(セル内)の上下に多少の余白が欲しかったので、 「折り返して全体を表示する」は使わないようにしました。
- hallo-2007
- ベストアンサー率41% (888/2115)
勘違いと思いますが Cells(i, 6) では F列ですよ Cells(i, 7) 或いは Cells(i, "G") Range("G" & i)という記述方法もあります。 ElseIf 73 < Cells(i, 6) < 108 Then も ElseIf Cells(i, 6) < 108 Then で十分です。 この様な場合は Select CASE文を参考にしてください。 http://excelvba.pc-users.net/fol6/6_2.html などを参考に
お礼
llo-2007様 >勘違いと思いますが >Cells(i, 6) では F列ですよ すいません、勘違いです。 >ElseIf 73 < Cells(i, 6) < 108 Then も >ElseIf Cells(i, 6) < 108 Then >で十分です。 >この様な場合は >Select CASE文を参考にしてください。 今回の場合は、Caseの方が適していました。 勉強になりました。ありがとうございます。
- keithin
- ベストアンサー率66% (5278/7941)
エクセルの関数でもマクロでも同じですが,「A<X<B」なんて計算のさせ方はありません。(計算はエラーにはなりませんが,正しい計算結果を得られません) 誤り: ElseIf 73 < Cells(i, 6) < 108 Then 正解例: ElseIf 73 < Cells(i, 6) and cells(i, 6) < 108 Then 以下同文で,すべて修正します。
お礼
keithin様 >エクセルの関数でもマクロでも同じですが,「A<X<B」なんて計算のさせ方はありません。 >(計算はエラーにはなりませんが,正しい計算結果を得られません) 勉強になりました。 ありがとうございます。
お礼
Randomize様 丁寧な説明ありがとうございます。 なぜ自分のVBAが起動しなかったのかが、よくわかりました。 またこれからのアドバイスまでありがとうございました。 他の方と迷いましたが、上記の点からRandomize様をベストアンサーにしました。 (正直、他の方に教えて頂いたVBAでうまく高さの調整ができましたので、迷いました・・・)