tagCANDY CGI VBレスキュー(花ちゃん)の Visual Basic 6.0用 掲示板 [ツリー表示へ]   [Home]
一括表示(VB6.0)
タイトルシートのActiveXコントロールの内容が表示されない。
記事No16570
投稿日: 2020/05/13(Wed) 20:02
投稿者悩めるEXCELマクロ士
いつもお世話になっています。
早速ですが質問です。
当方では、現在EXECLを使用してSQLServerからデータを取得。
それをシートに出力してグラフを作成してそれをプリントスクリーンして
グラフを画像としてEXCELに添付して提出帳票を作成するアプリを作成しています。
サーバからのデータの取得、シートへの貼り付けグラフの表示、各計算処理など
うまくいったのですが、グラフをプリントスクリーンして画像として
シートに張り付けるところがうまくいかず悩んでいます。
うまくいかない現象としては、プリントスクリーンをしてクリップボードから
画像をシート張り付けると、シート内にあるActiveXコントロールのラベルに
入力した値が表示されないという現象です。
プログラムとしては、

Sub SheetPrint()
  WorkSheets("Sheet1").Active
  WorkSheets("Sheet1").Range("A1:R37").Select
  WorkSheets("Sheet1").Range("A1:R37").CopyPicture appearance:=xlScreen, Format:=xlPicture
 Worksheets("Sheet2").Paste Range("B2")
End Sub
というような、プログラムを組んでいます。
この状態で、張り付けられた画像を見ると、グラフは表示されているんですが
ActiveXのラベルの内容は空白なってしまっています。
あだ、Subでブレイクをして1ステップずつ送りながら行うとActiveXの内容も表示された
画像が張り付くので、タイミングかと思い、「.Active」のあとに
「Application.Wait [Now()] + 5000 / 86400000」を入れて5秒待ちを作ってみたのですが
状況は変わりませんでした。
どのような解決策があるか、どなたかご教授いただけると助かります。
よろしくお願いします。

[ツリー表示へ]
タイトルRe: シートのActiveXコントロールの内容が表示されない。
記事No16572
投稿日: 2020/05/13(Wed) 21:49
投稿者魔界の仮面弁士
> WorkSheets("Sheet1").Active
> 「.Active」のあとに
Active …?
Activate ではなく?


> ActiveXのラベルの内容は空白なってしまっています。
フォーム コントロールの Label ではなく、
ActiveX コントロールの方の Label なのですね。

ラベルの内容を、コードで書き換えてから撮影しているのでしょうか?
それが反映されないのだとしたら、メッセージループが処理されていないからでしょう。


> 「Application.Wait [Now()] + 5000 / 86400000」を入れて5秒待ちを作ってみたのですが
時間の問題ではなく、ビジー状態か否かという点だと思います。
Label の内容を書き換えたとしても、その内容が画面に反映されるのは、
通常、イベント処理の終了後になるからです。

ActiveX コントロールの描画が更新されるには、Excel が
ユーザー操作を受け付ける状態になっていなければなりません。

たとえば
 Application.Wait DateAdd("s", 5, Now)
などで 5 秒間待機させると、VBA 側のタイトルバーに "[実行中]" と
表示された状態のまま待たされます。

この間、Wait が終わるまでユーザー操作を受け付けないビジー状態となるため、
画面の描画は直ちに更新されず、後回しにされます。

ユーザー操作を受け付ける状態…たとえば、VBA のブレイク中や、
VBA コードの実行が終わってアイドル状態になっている時、あるいは、
MsgBox や InputBox などが表示された場合など…であれば、
その時点で再描画が実施されます。


経験則になりますが、コード中で強制的に再描画したい場合は、
 Dim w As Double
 With 対象のラベル
  w = .Width
  .Width = w + 10
  .Width = w
 End With
などとしてリサイズしてやると、描画結果が更新されるかと思います。
すべてのコントロールに有効な方法というわけではないですが、
Label が相手ならこれでいけるでしょう。



> WorkSheets("Sheet1").Range("A1:R37").Select
> WorkSheets("Sheet1").Range("A1:R37").CopyPicture appearance:=xlScreen, Format:=xlPicture
手元の環境で試したところ、非表示なシート上のセル範囲やチャートであったとしても、
CopyPicture は動作しました。わざわざアクティブ化する必要は無いかもしれません。


>  Worksheets("Sheet2").Paste Range("B2")
引数に渡している Range("B2") が、どのシートを指しているのか曖昧な表記なので、
親となるワークシートを添えて、明示的に指定した方が良いと思います。


> この状態で、張り付けられた画像を見ると、グラフは表示されているんですが
張り付け → 貼り付け

[ツリー表示へ]
タイトルRe^2: シートのActiveXコントロールの内容が表示されない。
記事No16575
投稿日: 2020/05/16(Sat) 21:18
投稿者悩めるEXCELマクロ士
魔界の仮面弁士 さま

お世話になります。返信が遅くなってしまって申し訳ありませんでした。

> Active …?
> Activate ではなく?
『Activate』の間違いでした。

> 時間の問題ではなく、ビジー状態か否かという点だと思います。
なるほど、やはりそうですよね。何度か手直しをしているうちに
なんとなくそうではないかと思っていました。

とりあえず、当方の環境を説明していなかったので書きます。
OS  :Windows10
Office:Office365 32ビット版
です。
EXCELとしては、シートの数は設定シートなどを含めて20シートほど
そのうち、メニュー画面として使っているシートグラフを表示するシート
スクリーンショットで撮影した画像を貼り付ける為のシートがあります。
メニューシートには、ActiveXのCommandボタンを配置してあるだけで
クリックするとユーザーフォームが起動して日付とコードを入力。
作成ボタンを押すとグラフ作成と画像貼り付けを行うプログラムが走る
というような流れです。
で、結論からいうとお教えいただいた方法をベースに試作したところ
なんとか表示さるようになりました。
ですが、新たな問題として連続して同じ処理を実行するとEXCELがフリーズ
してしまうという現象が出るようになってしまいました。
試作したプログラムを記述すると

Sub Graph_CopyPast()

  Dim w        As Double
  Di tmpCNTNM  As Variant

  Application.ScreenUpdating =True
  
  With Worksheets(グラフシート名)
     For Each tmpCNTNM In .OLEObjects
         DoEvents
         Select Case True
             Case Instr(tmpCNTNM.Name,"lbl") >= 1 Or _
                               Instr(tmpCNTNM.Name,"cmb") >= 1
               w=tmpCNTNM.Width
               tmpCNTNM.Width=w+10
               tmpCNTNM.Width=w
         End Select
     Next tmpCNTNM
     .Range("A1:R37").CopyPicture Appeaance:=xlScreen,Format:=xlPicture
     Worksheets(画像貼り付け先シート名).Past Worksheets(画像貼り付け先シート名).Cells(5,9)
     Application.CutCopyMode=False
  End With
  
  Application.ScreenUpdating = False

というプログラムです。
解説すると、
最初に『Application.ScreenUpdating =True』しているのは、
実行ボタンが押されたときに画像描画を止めるため、『False』に
しているためです。
何度かやってみたんですが、これをTrueにしないと空白の枠だけが
ペーストされるだけになってしまうので、これを入れています。
本当は画像更新しているところ見せたくないので『True』に
したくないのですが。
次に、『For Each』ですがグラフ作成シートには
グラフデータから最大値や最小値、平均や中間値などを計算した
結果を出力するためActiveXのコントロールが『26』個程あるので
それをループで回して、名前の接頭語で判断して区別しています。
で、あとは教わった方法で強制的に再描画をさせています。
とりあえず、この方法でEXCEL起動後最初の1回目は問題なく
動作するんですがその後連続で同じ処理を実行すると、
『Past』のところで
『RangeクラスのCopyPictureメソッドが失敗しました』や
『処理を続行するにはメモリが不足しています。』
などのエラーが出るか、そのままEXCELがフリーズして処理が
止まります。
一応、1回目は処理が完了するのでいいといえばいいのですが
やはり、やり直しなどが発生した場合にいちいちEXCELを
再起動させていたのではシステムとして使いづらいと思うので
何とか安定して2度、3度と処理ができるようにしたいと
思っています。
何か、良い方法はないでしょうか。
乱文、長文になってしまって申し訳ありませんが
よろしくお願いします。

[ツリー表示へ]