• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:エクセルVBAで列幅設定)

エクセルVBAで列幅設定

このQ&Aのポイント
  • エクセルVBAを使用して、A列の幅をC〜F列の幅に設定したいが、ColumnWidthとWidthの単位の違いによりエラーが発生する。
  • 同じ単位で設定するためには、Columns("A").ColumnWidthにColumns("C").ColumnWidth + Columns("D").ColumnWidth + Columns("E").ColumnWidth + Columns("F").ColumnWidthを代入する必要がある。
  • より簡単な方法はわからない。

質問者が選んだベストアンサー

  • ベストアンサー
  • cj_mover
  • ベストアンサー率76% (292/381)
回答No.5

#3、4、cjです。 #4投稿して30分後に新たに#3補足欄が投稿されたのを受けて#3補足欄へのレスです。 たぶん、#4を見る前に書かれたものなのかな?と思っていますけれど、 こちらの主旨が伝わっていない、ということだけは、よりハッキリしましたので、 相も変わらず下手な説明しか出来ませんが、もう少し書いてみます。 > すみません、以下のようにやってみました。 > 結合セル(C~F)の各セルColumnWidth合計と一つのセル(M)のColumnWidthは同一です。 はい、そのようにした時の、 "各セルColumnWidth合計と一つのセル(M)のColumnWidthは同一"ですが、 【結合セル(C~F)全体】の横幅 > 【単セル(M)】の横幅、 この、実際の横幅の違い、引いては、1行で表示可能な文字数の違い、に目を向けて貰いたい、 ということを伝えようと一連の回答を投稿しているのです。 > フォント種類サイズも同一です。しかし、不完全なものになってしまいます。 単純にColumnWidth合計を基準にしている限りは避けられない不完全さ、と思いますが、 確かに私の環境でも、#3補足欄のコードを走らせた結果は、 行高が合わないですし、それ以前に列の幅が違っていますので。 当初の質問文と#3補足欄でご提示の記述では正しい列の幅がトレース出来ていません。 まず「Excel用語としての列の"幅"=ColumnWidth」の数値を見るのではなくて 「絶対的な列の幅」がきちんとトレース出来ているか視覚的に確認してみてはどうですか? 簡単な確認方法として(#3でも触れているように)C:F列の結合セルをひとつ選んで色付けしてコピーして、 それをA列なりM列なりに[図]として貼り付ければ、「絶対的な列の幅」の合否を視認できると思うのですけれど。 「Excel用語としての列の"幅"=ColumnWidth」 と 「Excel用語としての(列の幅に関する)"ピクセル"∝Width」 とでは、単位が違うということだけではなくて算出方法が違う、ということなのです。 例えば #3で示したC:F列については、{5,3,6,7}という「Excel用語としての列の"幅"=ColumnWidth」 になっていますので、【それぞれの列】に表示可能な文字数を合計すると、21、になります。 ところが、C:F列にセルの結合を適用した場合は、C:F列全体に表示可能な文字数は、23弱、です。 なので、A列なりM列なりに「絶対的な列の幅」をトレースする必要があって、 その値をColumnWidthに換算すると、凡そ、22.88、になります。 つまり、(今回のように複数列を扱う場合は) 「Excel用語としての列の"幅"=ColumnWidth」を単純に加算したものを列の"幅"に指定しただけでは、 「絶対的な列の幅」よりも小さな幅になってしまう、ということです。 #3での提案の繰り返しになってしまいますが、 【結合セル(C~F)全体】の「Excel用語としての(列の幅に関する)"ピクセル"∝Width」を基準に 【単セル(M)】の.ColumnWidthに換算した上で設定する方が、楽なのでは? C:F列の結合セル全体の、「Excel用語としての(列の幅に関する)"ピクセル"∝Width」、を取得して、 この∝(比例)関係(フォント由来)を、/ 8 PixelとScreenのXSize(横方向サイズ)の∝(比例)関係を逆数で、* 4 / 3 元々セルの[余白]としてのサイズを、-5 のように演算して求めた結果を A列なりM列なりの「Excel用語としての列の"幅"=ColumnWidth」として設定してあげる、 という例を示したつもりなのです。 それぞれのパラメータを汎用的に取得することは可能でしょうけれど、 そもそもが"もっと簡単な方法はないでしょうか?"というご質問を受けての回答ですから、 あとは調整、修正、運用、の範疇でこなして貰えたら、って思うのです。 まぁ、こちら説明が下手で話が噛み合わないようでもあるので、同じ話はこれぐらいにしておきますが、 どうしても「Excel用語としての列の"幅"=ColumnWidth」だけで実現させたい?という特別なお考えでしたら、 "簡単"ではないにしろWeb上に情報はあるようですし、私の回答に際しての内規からは逸れてしまいますので、 本当にすみませんが、お応えするつもりはありませんので、あしからず。 ただ何ていうか、この課題、Excelクンの一般機能面がもう少し易しい設計だったら悩まずに済むのになぁ、 と思うことが何点かあって、そういう意味では、考えさせられる事が多くて刺激的でありました。 では、また。

emaxemax
質問者

お礼

すみません、回答4があるのを気づかないで書いてしまいました。 注意不足のうえ理解が悪くすみません。 Columns("A").ColumnWidth = (Range("C1:F1").Width * 4 / 3 - 5) / 8 この換算式でうまくいきました! なんどもありがとうございます。 これでうまくいったと思ったら、また難題が一つ。 それは別質問といたします。 ありがとうございました。

その他の回答 (4)

  • cj_mover
  • ベストアンサー率76% (292/381)
回答No.4

#3、cjです。お礼欄のみ投稿されている時点でのお礼欄へのレスです。 > 正しくは、列幅というより表示出来る文字数でした。 #3の回答主旨に沿って言えば、仕様(1)絶対的な幅(ピクセル幅)ということのようです。  [列幅](Excelの用語) = (フォントの種類とサイズに準じて)表示可能な文字数によって表す列の幅  [文字数](便宜上の用語) = 表示可能な文字数  [文字幅単位](便宜上の用語) = (フォントの種類とサイズに準じて)基準となる1文字に割り振られる[ピクセル]値  [余白](便宜上の用語) = 表示に必要な幅に加える余地。1列にひとつ設定される。   ※何れも[表示100%]を基準にしますが、異なるズーム表示したもの同士を比較した場合に表示可能な文字数が変化するだけで、   [列幅]と[ピクセル]の相対関係はズームに係りません。 という風に定義したとすると、   [列幅]で表す[文字数] * [文字幅単位] + [余白] という風に絶対的な幅が【各列毎に】決まっているので、 "複数列[列幅]の合計"から"単列の[列幅]"を設定しようとすると、列数に比例した[余白]の分の誤差が出てしまいます。 > 実は、レイアウトの都合上、どうしても一部の行で複数列を結合した表をつくらなければなりません。そしてそこに自動表示させるのは、計算によって求められらたある値に対応する長文の文字列なのです。 > この長文文字列を折り返して表示させるのですが、表示させるのは数種類のうちの1つなので、行の高さをあらかじめ固定できません。 > しかし行の高さの自動調整は結合セルでは使えません。そこで同じ行に、結合させる複数列と同じ幅の1列を作って、そこにいったん長文を折り返して表示させ、そこで行の高さの自動調整をかける仕掛けを作っていたのです。 "数種類"というのがよく解りませんが、セル内で何行分文表示させる([折り返して全体を表示する]の仕様に準)か、 実行前に予測ができない、という意味かと思います。 フォントサイズが統一されているなら、とか、等幅フォントを使っているなら、とか、 条件によっては、簡単にできる部分もあるでしょうけれど、この手の課題は汎用性を考えることで、 周りからは手が付けられない課題になってしまうことが多いです。 「結合セルについて[折り返して全体を表示する]機能の自動に準じた行の高さを設定する」ということでしたら、 それはそのテーマで質問してみてもいいかも知れません。 その場合は、環境や条件を限定するか、または汎用型を求めているとハッキリ意思表示するかすれば、 役立つ回答も付き易いと思います。 [折り返して全体を表示する]機能も実は必要以上の行高を返したり(1行分多かったり)する場合が多いので、 必要十分な行高を返すように書く他のアプローチでも結構悩んだ覚えがあります。 また、印刷した時の仕上がり、とか、ページレイアウトへの影響とか、も考慮するべきかも知れません? 不得手な私には何が必要でどこまでやれば十分か判断がつきませんです。 簡易簡略、という方向で、とりあえず、#3の主旨にそって、 「ざっくり手抜き版」の仕様(1)に書き加えると、以下のような感じでも、まぁ、使えるのではないでしょうか? こちらの環境では、 A列の単セルとC:F列の結合セルで、[折り返して全体を表示する]機能による見かけ上の改行ポイントを揃えられること を確認しています。  4 / 3  5  8 などのパラメータはPC環境、フォントに合わせて変える必要がありますが、 書式としては共通している、と思います。 ' ' /// Sub Re8490019n()   Dim i As Long   i = 3   Columns("A").ColumnWidth = (Range("C1:F1").Width * 4 / 3 - 5) / 8   With Cells(i, "A")     .WrapText = True     .Value = Cells(i, "C")   End With End Sub ' ' ///

emaxemax
質問者

お礼

ありがとうございました。 たすかりました。

  • cj_mover
  • ベストアンサー率76% (292/381)
回答No.3

こんにちは。お邪魔します。 ちょっと、やりたい事の解釈に迷っていましたが、 何故迷ったのか、の説明から始めます。 とりあえず、添付画像をみてください。 それぞれ1行めの黄色い背景色で示しているのは、 「範囲C:Fの幅」(Excelシート上での絶対幅)を表す比較用のスケールです。 また、半角"0"を21桁、統一して並べているのも比較の為です。 添付画像の仕様(1)と仕様(2)で何が違うかというと、 仕様(1)は、 「範囲C:Fの幅」をピクセルで採ったものを「A列の幅」として適用しています。 対して仕様(2)は、 「範囲C:F各列の表示可能な文字数(によって決まる幅)の合計」を「A列の表示可能な文字数(によって決まる幅)」として適用しています。 仕様(1)は範囲C:F全体の絶対的な幅、 仕様(2)はセルの幅をセル内に表示出来る文字数で解釈した幅の合計です。 元質問でご提示のふたつの例は、どちらも(2)のような結果を返しますが、 "A列の幅を、C~F列の幅に設定"、、、ということだと、ちょっと違うようにも思えたりしました。 仕様(2)のような結果を求めているのであれば、一例めの > Columns("A").ColumnWidth = Columns("C").ColumnWidth + Columns("D").ColumnWidth + Columns("E").ColumnWidth + Columns("F").ColumnWidth のようなやり方で十分、シンプルな記述と言えるように思います。 ちょっと脇に逸れますが、.ColumnWidthについて、 VBAのヘルプでは、 > 列幅の単位は、標準スタイルの 1 文字分の幅に相当します。プロポーショナル フォントでは、数字の 0 の幅が列幅の単位になります。 と説明されています。 Excelの[オプション][基本設定][新しいブックの作成時]の [使用するフォント]と[フォントサイズ]で設定された値によって、返す値が違ってくる、 ということのようです。 という前置きをしておいて、 例えば、自分の仕事環境だと、フォント:「MS P ゴシック」、フォントサイズ:「11」という (ありきたりな)基本設定で(その他の環境も)統一されていたりするので、 簡便さだけを追求して決め打ち的に、ざっくりと手抜きをして、次のような方法もアリなのかも知れません。 (検証不十分かも?ですけれども(^^;)、、、)  仕様(1)   Columns("A").ColumnWidth = (Range("C1:F1").Width * 4 / 3 - 5) / 8  仕様(2)   With Range("C1:F1")     Columns("A").ColumnWidth = (.Width * 4 / 3 - .Columns.Count * 5) / 8   End With 仕様(1)については、もう少し汎用的な例をひとつ。 Range("C1:F1").WidthとRange("A1").Widthでピクセル幅は取得出来るので、 ピクセル幅が同値になるまでループして、 Range("A1").ColumnWidthを繰り返し設定し直す、みたいなこと、昔書いてた覚えがあります。 実際はAPIとか組み合わせた方がいいんでしょうけれど、とりあえず、パラメータは適当に書いています。 こんなアプローチもアルって紹介程度で、、、。 Sub Re8490019jj()   Dim dblTgtWidth As Double   dblTgtWidth = Range("C1:F1").Width   Application.ScreenUpdating = False   With Range("A1")     ' ' 横幅を一旦、小さめに設定     .ColumnWidth = dblTgtWidth * 0.16   '  「4:3画面」なら * 0.117  数値は大き過ぎず適当に     ' ' 横幅を一旦、やや大きめに設定     ' ' 横幅が目標値より小さい間ループして、1/2文字分ずつ横幅を拡げる     Do While dblTgtWidth > .Width       .ColumnWidth = .ColumnWidth + 0.5   '  数値は大き過ぎず適当に     Loop     ' ' 横幅が目標値より大さい間ループして、指定の精度ずつ横幅を狭める     Do While dblTgtWidth < .Width       .ColumnWidth = .ColumnWidth - 0.068    '  数値は小さ過ぎず適当に     Loop   End With   Application.ScreenUpdating = True End Sub (私は印刷関連の扱いが不得手ですので、以下の説明に出てくる"幅"についてはあくまでも  PC画面に表示されたExcelシート上でのお話です。  また、各種PC環境やバージョンの違いについても疎い私です。) 以上、ご参考まで。

emaxemax
質問者

お礼

ありがとうございます。 質問の意図をもっと詳しく書いとけばよかったですね、すみません。 正しくは、列幅というより表示出来る文字数でした。 実は、レイアウトの都合上、どうしても一部の行で複数列を結合した表をつくらなければなりません。そしてそこに自動表示させるのは、計算によって求められらたある値に対応する長文の文字列なのです。 この長文文字列を折り返して表示させるのですが、表示させるのは数種類のうちの1つなので、行の高さをあらかじめ固定できません。 しかし行の高さの自動調整は結合セルでは使えません。そこで同じ行に、結合させる複数列と同じ幅の1列を作って、そこにいったん長文を折り返して表示させ、そこで行の高さの自動調整をかける仕掛けを作っていたのです。

emaxemax
質問者

補足

すみません、以下のようにやってみました。 結合セル(C~F)の各セルColumnWidth合計と一つのセル(M)のColumnWidthは同一です。 フォント種類サイズも同一です。しかし、不完全なものになってしまいます。 Sub test03() Dim c As Range Dim x As Single Dim i As Long For Each c In Range("C1:F1") c.Value = c.ColumnWidth x = x + c.ColumnWidth Next Columns("M").ColumnWidth = x Range("M1").Value = Columns("M").ColumnWidth For i = 2 To 10 Cells(i, "M").Value = Cells(i, "C").Value Next Rows("2:10").AutoFit End Sub

回答No.2

すでに出来上がっているものに対して、更によい方法をないかとお探しになるのは結構ですが、それは、ご自身で考えてみてください。掲示板で、他人の知恵を借りても、勉強にはなりません。 >手の込んだことをするしか思いつきません。 あなたが、非常に敏感で、1000分の1秒単位を感知するというなら、おそらく外部の言語で作らなくてはなりませんが、今度は、オーバーヘッドに手間が掛かってしまいます。 こんな単純なコードに手を加える必要などはまったくありません。 >Columns("A").ColumnWidth = Columns("C").ColumnWidth + Columns("D").ColumnWidth + Columns("E").ColumnWidth + Columns("F").ColumnWidth そう思うのは、心理的に、おそらく、Excelのワークシートでの関数式のこだわりを、VBAのコーディングに持ち込んだからだと思います。 ColumnWidth というプロパティは、あくまでも、1列に対しての幅のことです。 範囲をまとめても、「C~F列の幅(同一ではありません)」でないなら、Null値が返るはずです。したがって設定できません。 複数列が同一だったら、その一つの幅しか出ません。もともと、定型シートなら、最初から、「キメウチ」として、要求する数値を入れたほうが早いです。 それがいやなら、どこかに、隠しセルにでもして、関数で、セル幅の合算を出すようにすればよいです。もしくは、マクロでその度ごとに、数式をセル上に書くか、Evaluateで出すか、ですが、今までよりも、エラーの発生が多くなる劣ったコードになるはずです。 こんなコードは、意味はないと思いますが、一例です。 例: H1: =CELL("width",C1)+CELL("width",D1)+CELL("width",E1)+CELL("width",F1) '*セル幅の合算をひとつのセルに出しておきます。 '// Sub Test2() Dim Wd As Variant 'セル幅の合算 Wd = Range("H1").Value If VarType(Wd) = vbDouble Then   Columns("A").ColumnWidth = Wd End If End Sub '//

emaxemax
質問者

お礼

ありがとうございます。 このような方法はまったく思いつきませんでした。 (CELL関数をよく知らないので当然ですが) 勉強になります。

  • bin-chan
  • ベストアンサー率33% (1403/4213)
回答No.1

EXCELを使える環境でなため、未テストですが Range("C1:F1").select Columns("A").ColumnWidth = Selection.ColumnWidth でどうでしょう?

emaxemax
質問者

お礼

ありがとうございます。 残念ながら、Range("C1:F1").ColumnWidth と同じで、Null値が返るのでエラーになります。

関連するQ&A

専門家に質問してみよう