• ベストアンサー

プロポーショナルフォントの文字列から印刷幅を求める関数

フォントと文字列を指定して必要なピクセル数を求める関数はありますか 備考欄なのですが2文字程度のあふれなら縮小、それ以上なら改行して全体表示させるマクロを作りたいのです 固定長フォントにすれば文字数から判断できますがPフォントなので 別シートに該当文字列を入れてAutoFitして求めることも考えましたがあまりスマートじゃないで 何かで見た記憶があるのですがVBAじゃなかったのか探しても見つから無かったので質問させていただきます。

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

  • ベストアンサー
  • end-u
  • ベストアンサー率79% (496/625)
回答No.7

検索してみたら、APIのGetTextExtentPoint32関数で取れそうな感じですが... http://msdn.microsoft.com/ja-jp/library/cc410400.aspx よくわかってないのでハズしてたらすみません。 『No16666.テキストボックスからはみ出た文字を削除する方法』 http://www.accessclub.jp/bbs2/0051/beginter16666.html ここを参考にテストしてみて、Pフォントの各文字幅が取れるところまでは確認しました。(文字列全体も) Function GetTextExtent にControlではなくFontを渡すように修正したり、 dxdy.cx取得後の変換が必要だったりするような感じではありますが。

noah7150
質問者

お礼

end-uさん度々の回答ありがとうございます。 こんな凝った質問に答えていただき感謝、感謝 KenKen_SPさんやend-uさんから教えていただいたWindows GDI系のAPI関数から取れそうな気がします。 ただ、別件で急ぎがあり確認している時間が今は無く 近々に確認し報告したいとは思いますが、このスレッドでは出来そうにありません。 うまくいきましたら同様の質問に回答させて頂くことで報告とさせてください。 でもこんなマニアックな質問する人が他に要るのか疑問 そんな人は解決方法を自分で見つけるような気もしますけど

その他の回答 (6)

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.6

こんにちは。 #4 です。 少し、コメントです。 >多分プリンターとAPIで会話してるとは思っていません >ドライバーにそこまでの機能を持たせるか疑問もありますし ドライバの機能は関係ありません。API は、Excelとプリンタ側のインターフェイスがあるのだと考えるのは当然だと思います。結局、公開されなかったように思います。こちらがずっと何年もかかって考えてきたものを否定するのは自由ですが、そのような目算があるなら、ご自身でコードが書けるのでは?

noah7150
質問者

補足

あは!怒らせてしまいましたかね。 いや、典型的なSEさんのようですね。 やはり物作りをする人は信念をもってないといけません。 言葉足りずですね。 >多分プリンターとAPIで会話してるとは思っていません は APIでプリンタ側のインターフェイスとのやり取りを一切やっていないとは思っていません。 今回のフォントに関しては直接やっていないと思っているだけです。 当然ながらプリンタの状態を調べるコマンドはあると思います そして基本的な事はドライバーがやってると思ってます。 なぜなら前回の回答へのコメントで書きましたが 本体を接続しない状態や電源が切れている場合、プリンターと会話することは出来ませんから。 でもプレビューやプリンターの設定等は問題なく出来ます ドライバーと会話しているのだと理解しています。 私は良く客先環境と出来る限り同じ状態でテストしたいのでプリンタードライバーのみをセットして実行させることがあります。 当然、プリンターをマシンに接続していません、同じものが手元に無いから。 上下左右の印刷できない部分が機種により違うため テストで1枚に収まっていても現地で出力すると2ページになることが何度かあったからです。 プレビューでもなるのですけどね 直接、印刷するものは分かりません プレビューに変更し確認しておいて印刷戻し実行すると スプールにページ数が出るので2ページならないかを見てます。

  • KenKen_SP
  • ベストアンサー率62% (785/1258)
回答No.5

仮にそのような便利なプロパティー・メソッドがあったとしても 公開されてないのでは、自力計算するしかないでしょう。 多分、プリンタのデバイスコンテキストに CreateFont、DrawText で計算できると思う。 DrawText の第4引数 Rect 構造体に実際の描写サイズがピクセル で返されます。つまり、まず標準フォントの 0(ゼロ)の 横ピクセル数X1を求め、次に目的の文字列の世サイズX2を測る。 ColumnWidth に設定すべき値W(単位:標準フォント文字数)は    W = X2 / X1 で求まる...と思う(・∀・)

noah7150
質問者

お礼

回答ありがとうございます。 >多分、プリンタのデバイスコンテキストに CreateFont、DrawText >で計算できると思う。 『そういえば昔、Access2000でレポートで作図したときに使ったなぁ 窓空きの住所・氏名印字欄を角丸で囲んだりしたなぁ』 なんて、なんか思い出したような…。 もしかすると使えるかも。 AccessのVBAにあってもExcelのVBAにあるのかなぁ こんなことしてると仕事より趣味の世界に入りそう。 全半角混在だと勝手に全半角位置で勝手に折り返したりするので 100%というわけにはならないのは分かっているのですけどね

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.4

こんにちは。 中をよく読んでみると、最初の質問タイトルと内容が若干違うようですが。 印刷の長さを求める話と、セルの文字があふれるかどうかとは、まったく別問題のはずです。 >固定長フォントにすれば文字数から判断できますがPフォントなので 今、試してみると、AutoFit に対しては、それほどに違いがないようですが。 #3のend-uさんの着目点にある、マージンは、私は、以前、「調整余白」という名前を付けましたが、 /S|FONT|s|FONT|s|FONT|s|FONT|S/ ということで、これが、プロポーショナルの場合は、Sもs も微妙に変わって、文字列が、セル長になると一文字ぐらい変わってしまうようです。 それぞれのセルの中のフォントの種類、フォントの大きさ、文字列等の長さ、そして、それらのセルの数によって、印刷時にその縦と横が微妙に変ってくる、と考えています。そこに「調整余白」が働きます。 >別シートに該当文字列を入れてAutoFitして求めることも考えましたがあまりスマートじゃないで AutoFit でも、それで本当に取れるなら良いのではないでしょうか? 実行する前に、Width を取っておいて、必要なければ、また元に戻せばよいです。 >フォントと文字列を指定して必要なピクセル数を求める関数はありますか ピクセルではなくて、幅に対するポイントだと思います。ピクセルでは、正しく出てきません。 実数値から定数を出すしかないと思います。そこから、一定の係数は出せませんでした。とは言っても、コードがないと話にならないと思います。(最後に書きます) >Excel自身がAutoFitやAutoSizeに必要で求めるはずなのでどこかには必ずある これは、公開されていません。これは、Excel Application の持つ、APIでしょうけれども、Excel 4.0 マクロ関数にもありません。ずいぶん調べましたが、見当たりません。今回の要件とは話が違いますが、Excel自体から、APIによって、プリンター側から物理的な距離を取り出すことはしているのは想像できます。それを一旦、セルそれぞれに割り振りして、その数値を丸めて、再び、セルの数だけ足し算しているので、左端だけは設定できて、後はずれてしまうという現象は理屈には合います。 ------------------------------------------------ 「文字列がセル幅に入るかどうかをチェックするマクロ」 ずいぶん昔に作ったものですが、AutoFit よりも狭いと「文字列は入らない」と出てくるはずです。ただし、入らないとメッセージが返っても、表示する分には見かけ上は入ったように見えるはずです。 とはいっても、完成されたものではありません。おのおのの環境でも違ってくるはずですし、いずれは、Excelが人気が続いている限りは、できるようにはなるとは思いますが……。 '---------------------------------------------------------------- '書式スタイル・フォントのサイズは、11(10-12まではOKだったはず) '---------------------------------------------------------------- Const dPO As Double = 3.75 'ポイント定数 Const iK As Integer = 6 'セル幅定数 Const dALNMGN As Double = 0.2 '全角調整余白(マイナス分) Sub Test_Cell()   Dim myStr As String   Dim myStrLength As Long   Dim mgWdth As Double   Dim iFlg As Integer   Dim pt As Double   Dim Diff As Double   iFlg = 0   With ActiveCell     If TypeName(.Cells) = "Range" And .Width > 0 Then       mgWdth = .Width       myStr = .Value       myStrLength = LenB(StrConv(myStr, vbFromUnicode))       Diff = LenB(StrConv(myStr, vbFromUnicode)) - Len(myStr)       pt = Int(((mgWdth - dPO) / iK) * 100 + 0.5) / 100     End If     If InStr(1, .Font.Name, "P", 1) >= 4 Then       iFlg = 1 'プロポーショナルの場合       Diff = dALNMGN * Diff  '全角における調整余白     Else       iFlg = 0       Diff = 0     End If   End With   If pt > 0 Then     If Int(pt + 0.5 * iFlg + Diff) >= myStrLength Then       MsgBox "その文字列はセルに入ります.", vbInformation     Else       MsgBox "その文字列はセルに入りません.", vbCritical     End If   End If End Sub '-------------------------

noah7150
質問者

お礼

回答ありがとうございます。 >中をよく読んでみると、最初の質問タイトルと内容が若干違うようですが。 >印刷の長さを求める話と、セルの文字があふれるかどうかとは、まったく別問題のはずです。 そう取られましたか。 タイトルにはやりたい事、内容には何故そのようなことがしたいかを書いたつもりだったのですが 溢れるのが分かればVBAで自動縮小の設定、行高さの変更を行うことが出来ると思って >今、試してみると、AutoFit に対しては、それほどに違いがないようですが。 私も厳密に調べたわけではありません 単純にWIWIWとIWIWIでAutoFitを行うと幅が違ってくるので計算されているのかと思っただけです。 確かにAutoFitで得られる値は多少大きい値が返ってきているように思われました また、行高さを変えていますので2行になっていても自動で広くならないのでその行を見つけるのにも使いたいと思ったわけです。 >APIによって、プリンター側から物理的な距離を取り出すことはしているのは想像できます 多分プリンターとAPIで会話してるとは思っていません ドライバーにそこまでの機能を持たせるか疑問もありますし (プリンター本体と会話してることは無いと思います、電源を落としている・ドライバーだけで本体は未接続のこともありますので) また、現実印刷を行うと機種により微妙に違いがあることもあります これはプリンターのフォントで印字されているからだと思います コードつけて頂いてありがとうございました。

  • end-u
  • ベストアンサー率79% (496/625)
回答No.3

一応確認ですが、最初から[折り返して全体を表示する]に設定しておくのはナシなんですね? といってもダイレクトに幅を求める関数を提案できるわけではなくて、 >別シートに該当文字列を入れてAutoFitして求めること... よりちょっとだけ簡易な方法として Sub test()   Const MARGIN As Single = 15      With ActiveCell     If widthCheck(.Item(1)) > .Width + MARGIN Then       .WrapText = True     End If   End With End Sub Function widthCheck(r As Range)   Dim ret As Single      With r.Worksheet.TextBoxes.Add(0, 0, 0, 0)     .AutoSize = True     With .Font       .Name = r.Font.Name       .Size = r.Font.Size       .Bold = r.Font.Bold     End With     .Text = r.Text     ret = .Width     .Delete   End With   widthCheck = ret End Function ...こんなアプローチもあるのではないでしょうか。 #特定のシートならTextBoxes.Add/Deleteではなく、Visible = FalseにしてName指定でも良いと思います。

noah7150
質問者

お礼

回答ありがとうございます。 >一応確認ですが、最初から[折り返して全体を表示する]に設定しておくのはナシなんですね? いえいえ、設定してます。 でも1文字溢れただけで2行にするのも 備考欄なのでそれなりの幅があり1文字を入れて縮小してもそれど文字は小さくならないのです。 テキストボックスでサイズを求めるなんて考えてもなかった。 早速試してみます。 もう少し待ってやはり直接出来ないようならこの手法使わさせていただきます 『独り言』 Excel自身がAutoFitやAutoSizeに必要で求めるはず なのでどこかには必ずある もしかするとPrintImageのDrow系の所にあるかもなぁ 内部ルーチンで使えないのかもなぁ・・・

  • imogasi
  • ベストアンサー率27% (4737/17069)
回答No.2

関数は引数のセルの値を使って、セルの値を導き出すもの。 プロポーショナルフォントは見栄えを重視して縦横画数などで大きさを決めていると聞いている。文字数は何万もあり、プロポーショナルのタイプは有るかもしれないが、計算で求められるものではなかろう。ある文字を指定した場合、ピクセル数を書いた書物やWEBなど見たことない。エクセ関数ではそのピクセル数を求める関数はない。文字ごとピクセル数の表が見つかったとしても、エクセルにその表を持って検索して合計するのも表が膨大過ぎて馬鹿げている。 いままで9年ぐらいここの質問コーナーのエクセルの質問を見ているが、初めての質問タイプかなと思う。VBAの標準のメソッドプロパティを操る程度のプログラムでは実際のフォントからピクセル数を導出するコードは組めないとおもう(API以上で出来るかどうか)と思う。 エクセルでは、そこまでカバーしないということだと思う。DTPやWEBではそこまで要求があるかもしれないとは思う。 style.width の話が出ているが、VBSCRIPTにもそれらしきものは無いようだが。 VB.NETではWEBをカバーする関係で、そういう指定が出来るようだ。 マニアックにならずに路線変更を勧める。

noah7150
質問者

お礼

助言ありがとうございます。 >関数は引数のセルの値を使って、セルの値を導き出すもの。 あくまでもVBAの関数です。 >マニアックにならずに路線変更を勧める。 確かに。 入力中に1文字あふれて2行になると気付き縮小するのですが Excelは画面表示と印字では違いがあり画面上は収まってるのに印字すると溢れてることってありますよね 文字が切れると別な意味になったりすることもあるので 常に折り返してにしていれば良いのだけど最後の1文字のために2行に そしてページに収まらず2ページになるってこともあるので 私としてはそれほどマニアックとは考えていなかったんですけどね

  • ksys2009
  • ベストアンサー率33% (1/3)
回答No.1

javascriptのstyle.widthではないでしょうか。  javascript⇒vbscript⇒vbaになれば良いのですが。

noah7150
質問者

お礼

回答ありがとうございます。 javascriptですか・・・ さすがにjavascriptは使ったこと無いですね ちょっと記憶が薄れかけてるのでもう何年も前 多分レポートツールで直接、図形や文字列の描画で右寄せするため必要だったので使ったと思う。 やっぱり簡単なものは無いのかもね。 お騒がせしてすみません。

関連するQ&A