C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

ログ内検索
  • キーワードを複数指定する場合は 半角スペース で区切ってください。
  • 検索条件は、(AND)=[A かつ B] (OR)=[A または B] となっています。
  • [返信]をクリックすると返信ページへ移動します。
キーワード/ 検索条件 /
検索範囲/ 強調表示/ ON (自動リンクOFF)
結果表示件数/ 記事No検索/ ON
大文字と小文字を区別する

No.66599 の関連記事表示

<< 0 >>
■66599  C#でExcelシート上のチェックボックスの変更
□投稿者/ のぶ -(2013/05/10(Fri) 14:44:41)

    分類:[C#] 

    Excelのシート上にグループ化されたチェックボックスがあり
    その中のチェックボックスに対してチェックの状態を変更したく以下のようにしてみました。

    public void CheckedInGroupCheckBox(string sheetName, string groupName, string checkboxName)
    {
    Excel.Worksheet sheet = sheets[sheetName];
    Excel.Shapes shapes = sheet.Shapes;
    Excel.Shape group = null;
    Excel.Shape chk = null;

    Excel.GroupShapes g = null;
    for (int i = 1; i < shapes.Count; i++)
    {
    group = shapes.Item(i);
    if (group.Name == groupName)
    break;
    }
    g = group.GroupItems;

    chk = g.Item(checkboxName); // ★

    ReleaseObj(ref sheet);
    ReleaseObj(ref shapes);
    ReleaseObj(ref group);
    ReleaseObj(ref chk);
    }

    ★の位置で目的のチェックボックスは取得できますが、
    それに対してどの様にチェックを付ければいいのかが分かりません。

    検索してみると、(VBAだと?)Valueに対してtrue/falseを設定すれば出来そうですが、
    コンパイルエラーになってしまいます。
    また、Worksheet.CheckBoxesメソッドではグループ化されたものは取得できませんでした。

    ※まだ貼り付けたメソッド自体試行錯誤中なので「そもそもどうやってtrue/false設定すんだよ!」という部分はスルーしてください。
親記事 /過去ログ112より / 関連記事表示
削除チェック/

■66602  Re[1]: C#でExcelシート上のチェックボックスの変更
□投稿者/ ラリホー -(2013/05/10(Fri) 16:38:41)
    コンパイルエラーになる、とありますが、どんなコードを書いて、どんなエラーになったのでしょうか。
    もしかしたら単純なミスなのかも知れませんので、ご提示ください。
記事No.66599 のレス /過去ログ112より / 関連記事表示
削除チェック/

■66604  Re[2]: C#でExcelシート上のチェックボックスの変更
□投稿者/ のぶ -(2013/05/10(Fri) 17:15:14)
    No66602 (ラリホー さん) に返信
    ご回答ありがとうございます。

    > もしかしたら単純なミスなのかも知れませんので、ご提示ください。
    失礼いたしました。補足致します。

    ★の次の行に
    chk.Value = true;
    と書きました。
    そして、出てくるエラー内容は以下になります。
    === エラー内容 ===
    'Microsoft.Office.Interop.Excel.Shape' に 'Value' の定義が含まれておらず、
    型 'Microsoft.Office.Interop.Excel.Shape' の最初の引数を受け付ける拡張メソッドが見つかりませんでした。
    using ディレクティブまたはアセンブリ参照が不足しています。
    ==================

    このような状態になります。
    chk自体Shapeとして取得しているので、CheckBoxとして認識できていないせいだろう・・・
    とは思っていますが、何をどうしたらいいのかさっぱりです。

    あと、何気なくExcel.○○と書いてしまってありますが
    using Excel = Microsoft.Office.Interop.Excel;
    としてあります。

記事No.66599 のレス /過去ログ112より / 関連記事表示
削除チェック/

■66624  Re[1]: C#でExcelシート上のチェックボックスの変更
□投稿者/ 魔界の仮面弁士 -(2013/05/12(Sun) 12:58:14)
    No66599 (のぶ さん) に返信
    > Excelのシート上にグループ化されたチェックボックスがあり
    フォームコントロールのチェックボックスでしょうか。
    それともActiveXのチェックボックスでしょうか。

    前者であれば、Shape の DrawingObject プロパティから、Excel.CheckBox 型のオブジェクトを得られます。
    あるいは、ワークシートの CheckBoxes メソッド経由で得ることもできます。

    後者の場合は、DrawingObject から得たオブジェクトに対し、さらにその object プロパティを呼ぶことで、
    MSForms.CheckBox 型を得ることができるでしょう。


    > また、Worksheet.CheckBoxesメソッドではグループ化されたものは取得できませんでした。
    CheckBoxes メソッドという事は、フォームコントロール版(Excel.CheckBox) の方ですね。

    グループ化されている場合(Shape の Type プロパティが msoGroup の場合)は、
    御存じのように GroupItems 経由で、個々の Shape 要素にアクセスできます。
    それを、Type が msoFormControl になるまで再帰的に繰り返してみてください。

    該当する Shape にまで行き当たったら、あとは上記のように、Shape の DrawingObject プロパティから
    操作対象のチェックボックス型を得ることができるはずです。


    > 検索してみると、(VBAだと?)Valueに対してtrue/falseを設定すれば出来そうですが、
    > コンパイルエラーになってしまいます。
    Excel.CheckBox の場合も MSForms.CheckBox の場合も、Value プロパティでチェック状態が変わります。
記事No.66599 のレス /過去ログ112より / 関連記事表示
削除チェック/

■66638  Re[2]: C#でExcelシート上のチェックボックスの変更
□投稿者/ のぶ -(2013/05/13(Mon) 09:42:34)
    No66624 (魔界の仮面弁士 さん) に返信
    ご回答ありがとうございます。
    また、お返事遅くなり申し訳ありません。

    >>Excelのシート上にグループ化されたチェックボックスがあり
    > フォームコントロールのチェックボックスでしょうか。
    > それともActiveXのチェックボックスでしょうか。
    お察し頂けた様にフォームコントロールのものを使用しています。


    > 該当する Shape にまで行き当たったら、あとは上記のように、Shape の DrawingObject プロパティから
    > 操作対象のチェックボックス型を得ることができるはずです。
    chkを取得後、chkからDrawingObjectプロパティからさらにオブジェクトを取得することによって
    チェック状態の変更に成功いたしました。

    書き換えたコードも掲載させていただきます。
    一応目的は果たせたので解決済みとしますが、何か突っ込みどころがあるようでしたらお願いいたします。

    public void CheckedInGroupCheckBox(string sheetName, string groupName, string checkboxName)
    {
    Excel.Worksheet sheet = sheets[sheetName];
    Excel.Shapes shapes = sheet.Shapes;
    Excel.Shape group = null;
    Excel.Shape chk = null;

    Excel.GroupShapes g = null;
    for (int i = 1; i <= shapes.Count; i++) //Count未満でなぜ取得できていたのか・・・
    {
    group = shapes.Item(i);
    if (group.Name == groupName)
    break;
    }

    g = group.GroupItems;

    chk = g.Item(checkboxName);
    var ch = chk.DrawingObject; //DrawingObjectから取得
    ch.Value = true; //取得したオブジェクトに対してValueプロパティでチェック状態を変更する

    ReleaseObj(ref sheet);
    ReleaseObj(ref shapes);
    ReleaseObj(ref group);
    ReleaseObj(ref g);
    ReleaseObj(ref chk);
    }
記事No.66599 のレス / END /過去ログ112より / 関連記事表示
削除チェック/

■66639  Re[3]: C#でExcelシート上のチェックボックスの変更
□投稿者/ 魔界の仮面弁士 -(2013/05/13(Mon) 11:18:45)
    No66638 (のぶ さん) に返信
    > ReleaseObj(ref sheet);
    これって、おそらくは COM 解放の Marshal.ReleaseComObject ですよね。
    宣言は void ReleaseObj<T>(ref T) でしょうか。

    たとえば Shape は、Parent プロパティで Worksheet を返してきます。
    今の解放順を逆にして、子階層から処分した方が良いと思ます;念のため。

    > 何か突っ込みどころがあるようでしたらお願いいたします。
    ループ中のそれぞれの Shape/GroupShapes や
    DrawingObject も、 COM オブジェクトじゃないですかね。
記事No.66599 のレス /過去ログ112より / 関連記事表示
削除チェック/

■66643  Re[4]: C#でExcelシート上のチェックボックスの変更
□投稿者/ のぶ -(2013/05/13(Mon) 13:10:37)
    No66639 (魔界の仮面弁士 さん) に返信
    > ■No66638 (のぶ さん) に返信
    >>ReleaseObj(ref sheet);
    > これって、おそらくは COM 解放の Marshal.ReleaseComObject ですよね。
    > 宣言は void ReleaseObj<T>(ref T) でしょうか。
    お察しの通りCOM解放用のメソッドです。
    ただ、ジェネリックスは使用せずオーバーロードで・・・という恥ずかしい書き方をしていました。。。
    ジェネリックスについて完全に忘れていたので、以下の様に書き換えました。

    private void ReleaseObj<T>(ref T shape)
    {
    if (shape == null) return;
    while (Marshal.ReleaseComObject(shape) != 0) ;
    shape = default(T);
    }

    > たとえば Shape は、Parent プロパティで Worksheet を返してきます。
    > 今の解放順を逆にして、子階層から処分した方が良いと思ます;念のため。
    そうですね。他の時でしたら「使った逆順で解放する」と心がけていましたが、
    Excelの操作で頭がいっぱいでそこまで気が回っていませんでした。
    ご指摘ありがとうございます。


    > ループ中のそれぞれの Shape/GroupShapes や
    > DrawingObject も、 COM オブジェクトじゃないですかね。
    ループ中の場合も解放した方がいいのでしょうか?
    一応一番最後に
    ReleaseObj(ref g);
    という形でGroupShapesに関しては開放しています。

    for (int i = 1; i <= shapes.Count; i++)
    {
    group = shapes.Item(i);
    if (group.Name == groupName)
    break;
    ReleaseObj(ref group); // ←こうすべき??
    }
記事No.66599 のレス /過去ログ112より / 関連記事表示
削除チェック/

■66644  Re[5]: C#でExcelシート上のチェックボックスの変更
□投稿者/ 魔界の仮面弁士 -(2013/05/13(Mon) 14:08:38)
    No66643 (のぶ さん) に返信
    > if (shape == null) return;
    念のため、IsComObject も使った方が良いかも。

    > while (Marshal.ReleaseComObject(shape) != 0) ;
    FinalReleaseComObject というものもありますよ。

    自分の場合は、常に 0 まで解放されると都合が悪い場合もあったので、
    全解放/一回だけReleaseComObject の 2 パターンの実装を
    用意するようにしています。参考までに。

    > ループ中の場合も解放した方がいいのでしょうか?
    逆に質問です。

    たとえば i == 3 のときに groupName が見つかった場合、
    1番目2番目のオブジェクトは、元のコードではどのタイミングで
    解放されるでしょうか?

    ちなみに、for ではなく foreach だと、解放はさらに面倒なことになります。
    http://bbs.wankuma.com/index.cgi?mode=al2&namber=54129&KLOG=91


    AppDomain のアンロード時や、GC 回収以外のタイミングでの解放に任せるのであれば、
    あえて ReleaseComObject しないという選択肢もあるのですけれどね。
    http://social.msdn.microsoft.com/forums/ja-jp/csharpgeneralja/thread/0F210F52-3667-4E66-9DD6-4480EEDE48DE
記事No.66599 のレス /過去ログ112より / 関連記事表示
削除チェック/

■66651  Re[6]: C#でExcelシート上のチェックボックスの変更
□投稿者/ のぶ -(2013/05/13(Mon) 15:03:57)
    2013/05/14(Tue) 09:29:26 編集(投稿者)
    2013/05/13(Mon) 15:54:58 編集(投稿者)

    本題とずれすぎてしまったので、こちは解決済みとして締めたいと思います。

    No66644 (魔界の仮面弁士 さん) に返信
    何度もお付き合い頂きありがとうございます。

    >> if (shape == null) return;
    > 念のため、IsComObject も使った方が良いかも。
    >
    >> while (Marshal.ReleaseComObject(shape) != 0) ;
    > FinalReleaseComObject というものもありますよ。
    >
    > 自分の場合は、常に 0 まで解放されると都合が悪い場合もあったので、
    > 全解放/一回だけReleaseComObject の 2 パターンの実装を
    > 用意するようにしています。参考までに。
    今回は0まで解放してしまって大丈夫なので、IsComObjectによる判定と
    FinalReleaseComObjectによる全開放という形に変更しました。
    ご指摘ありがとうございます。
    private void ReleaseObj<T>(ref T shape)
    {
    //if (Marshal.IsComObject(shape) && shape == null) return;
    if (shape == null || !Marshal.IsComObject(shape)) return; //条件がおかしかったので修正
    //while (Marshal.ReleaseComObject(shape) != 0) ;
    Marshal.FinalReleaseComObject(shape);
    shape = default(T);
    }


    >>ループ中の場合も解放した方がいいのでしょうか?
    > 逆に質問です。
    >
    > たとえば i == 3 のときに groupName が見つかった場合、
    > 1番目2番目のオブジェクトは、元のコードではどのタイミングで
    > 解放されるでしょうか?
    確かにその通りですね。。
    都度解放していかなければ残りますね。
    #言われれば分かるけど、自分で思いつかない。。。んー・・・


    > ちなみに、for ではなく foreach だと、解放はさらに面倒なことになります。
    > http://bbs.wankuma.com/index.cgi?mode=al2&namber=54129&KLOG=91
    これは恐らく大変だろうなと感じて回避してました。
    と言ってもfor内で解放していなかったので結果としては同じ事してましたが・・・

    > AppDomain のアンロード時や、GC 回収以外のタイミングでの解放に任せるのであれば、
    > あえて ReleaseComObject しないという選択肢もあるのですけれどね。
    > http://social.msdn.microsoft.com/forums/ja-jp/csharpgeneralja/thread/0F210F52-3667-4E66-9DD6-4480EEDE48DE
    現状としては、Excel操作用のラップクラスを作成し、その中で色々な操作を完結できるようにし、
    Disposableパターンを適用してExcel.Applicationや、Excel.Workbooks等の解放をDisposeメソッド内で行っています。
    URLを拝見すると、任意のタイミングでGC.Collect()を呼び出せばReleaseComObjectがなくても大丈夫というように読み取りましたが、
    私の場合ですと、Disposeメソッド内で呼び出せば解放されるということでしょうか?
記事No.66599 のレス / END /過去ログ112より / 関連記事表示
削除チェック/



<< 0 >>

パスワード/

- Child Tree -