• Excelで VBAマクロをいじってるうちに不調になる話

    excelでVBAマクロを編集→保存しつつ実行ということを繰り返していると、突然エクセル(というかブック)が不調になってしまうことがある。
    ※個人的には「xlsブックが腐った」と呼んでいる。

    • ブックを開くだけで「ご不便をおかけして申し訳ありません。」ダイアログが表示され死んでしまう。
      →腹いせにエラー報告しまくったけど、どうなるものでもなく・・・。
      Faulting application excel.exe, version 11.0.8211.0, stamp 47dcb10b,
      faulting module vbe6.dll, version 6.5.10.24, stamp 464105f1, debug? 0,
      fault address 0x001ec79a.
    • コードを変更していないにも関わらず、実行できたりできなかったりする
      →同じコードなのに、「コンパイルエラー」が出るようになる
    • コードを変更していないにも関わらず、実行できたりエクセルごと落ちたりする

    ツールをお客様の前でデモってるときに、エクセルごと落ちてしまい、「自分の環境では動くんだけど」を地で行く展開に・・・。
    頭が痛い。

    こんなときのgoogle先生頼み。
    が、excelが落ちる話はよく出てくるけど、同じコードで実行できたりできなかったり、という話は見つけられなかった。

    再現コードは追及できていない。
    状況・事情は以下のとおり。
    • 運用時はExcel 2000
    • Excel 2003 SP3/Excel XP(いずれもWin XP Pro SP2)で再現
      →2000ではいまのところ未経験
    • データを入れるxlsブックと、マクロを格納するxlaに分けている
    • xlaが開かれるタイミングで自ツール用のメニューを追加する
      →いろいろ経緯があってこういうことに
      →ブックを開いた状態でxlaを開くと機能が有効になる、という使い方
    • VBA中で新しいブックを作成し、一部シートを削除している
      →MSのKBに、(Excel 2000だけど)シートの削除やブック保存と関連のありそうなものがあったから
      http://support.microsoft.com/default.aspx?scid=kb;ja;JP199212
    • クラスモジュールを使っている
    • フォームモジュールを使っている

    結局原因はまったくわかっていない。

    調査の過程で、
    • xlaを開く→ツール-マクロ-Visual Basic Editor→CTRL+Sで保存→Excel終了、を繰り返すだけでxlaアドインのファイルサイズが変わる。
      →何も変更しない状態で上書き保存を繰り返す。本事象の場合、290KB~400KBの間で変化した。
    • 更にウォッチしたら「xlaを開く→エクセル終了する」だけでファイルの中身が変わる
      →具体的な違いは分からないが、sha1ハッシュが変化することで確認した。Tortoise SVNで変更のチェックにひっかからないのは、ファイルの更新時刻が変化しないからか。
    ということに気付いた。

    全く根拠のない想像だけど、何かしらの内部状態・中間状態(parseとか?)をブックの中に保存しているんだろう、そしてこの部分に火種が潜んでるんだろう、と考えた。

    だったら、保存できなくしてしまえ、ということで、xlaファイルを「読み取り専用」にしたら、ハッシュ値の変化はなくなった。当然ながら。

    現在のところマクロ死亡は再現していない。
    これならいける、かも???



    元々、リリース候補の作成を、nantを使って1手順化していたのが幸いだ。
    1. マクロ編集
    2. 実行・確認(NGなら1に戻る)
    3. リリース候補作成
    4. テスト
    という流れ。
    nantスクリプトでattrib要素を用い、xlaファイルを読み取り専用にする。
    4でエクセルが落ちる現象が出た場合は、1に戻って保存で再挑戦。内部状態がまとも?になるまで繰り返す(うへ)。

    読み取り専用でも上書きは可能なので、マクロの差し替えもなんとかなる、と。

     
  • Excelで Chartオブジェクトだけ画像ファイルに保存

    xlsシート内にあるグラフだけを画像ファイルに保存したい。
    ※グラフシートでなく。

    リファレンスを調べるとChartオブジェクトにSaveAsメソッドがあるようなので、html形式で保存したらいけそうだなーと思ったが、やってみるとエラーになってしまいお手上げ(詳細割愛)。

    どうしたものかな、とgoogle先生で検索を繰り返したら、またもや2chのスレッドに答えそのものを発見。
    あなどれんな~。

    Exportメソッドというものがあるらしい。
    形式も指定できるが、省略してもファイル名の拡張子から適宜判断してくれる。便利。
    gif/png/jpgはいけた。

    ■export_chart.js

    var app = new ActiveXObject("Excel.Application");

    try {

    var book = app.Workbooks.Open( xlsブックのフルパス, true );
    var sh = book.Sheets( 1 );

    var co = sh.ChartObjects( 1 );
    var ch = co.Chart;
    ch.Export( 出力画像ファイルのフルパス );

    } catch( ex ) {
    throw ex;
    } finally {
    app.Quit();
    }

    ■試した環境
    Excel 2003 SP3 + XP Prof SP2(ja)
    Excel 2007 SP1 + Vista Ultimate SP1 x64(ja)