DOBON.NETプログラミング道掲示板

■34730 / 親記事)  二次元配列内の文字の置き換え
  
□投稿者/ Wan 一般人(4回)-(2021/05/22(Sat) 22:09:35)
  • アイコン環境/言語:[Windows10 VisualStudio2019 VB.net WindowsForm] 
    分類:[.NET] 

    Excelのあるセル範囲を1列だけ選択して配列に変換したとします。
    Dim Rng As Excel.Range
    Dim Arry As Object(,)
    Rng = myExcel.Application.Selection
    Arry = Rng.Value2
    すると、次のような二次元配列ができました。
    (1,1) a
    (2,1) b
    (3,1) c
    (4,1) a
    (5,1) b
    (6,1) d
    (7,1) e
    (8,1) a
    これが約1000行位あります。
    後に、Excelのセルに戻す必要性から、配列としての構造を変えたくありません。

    (質問)
    配列を検索してaをAに変換する方法を教えて頂けませんでしょうか?
    一旦、一次配列に変換してLinqを使って変換して、再び上記の形に再変換するしか無いのでしょうか?単純に二次元配列をループして一つずつ変換するしか無いのでしょうか?
    ※配列の構造はこのままで、検索+置き換えを行いたい。
    ExcelのRangeのままやった方がいいのかな?

    詳しい方いらっしゃいましたら教えて頂けないでしょうか?
    宜しくお願い致します。

マルチポストを報告
違反を報告
引用返信 削除キー/
■34733 / ResNo.1)  Re[1]: 二次元配列内の文字の置き換え
□投稿者/ 魔界の仮面弁士 大御所(1335回)-(2021/05/23(Sun) 12:53:19)
  • アイコン2021/05/24(Mon) 09:14:14 編集(投稿者)

    No34730に返信(Wanさんの記事)
    > 単純に二次元配列をループして一つずつ変換するしか無いのでしょうか?
    ループ処理したくなければ、Range オブジェクトの Replace メソッドを使って
    一気に置換することが使えます。
    Rng.Replace("a", "A", Excel.XlLookAt.xlWhole, MatchCase:=True)

    複雑な置換条件(たとえば If 判定を伴うなど)が必要な場合には向かないですけれどね。


    > Rng = myExcel.Application.Selection
    Application プロパティを使っておられるようですが、
    変数 myExcel が Excel.Application 型であるならば、
     Rng = myExcel.Selection
    だけで良いと思いますよ。

    myExcel が Excel.Application 型以外なのだとしたら、Application を
     myApp = myExcel.Application
     Rng = myApp.Selection
    のように別の COM 変数に受け取って、使用後に ReleaseComObject すべきです。


    > 一旦、一次配列に変換して
    一次配列(primary array)というのは
    一次元配列(one-dimensional array)のことですね。

    二次元配列だと「複数行複数列」を表現できますが、一次元配列で書き戻した場合は、
    「単一行複数列」の意味になります。もしも一次元配列を複数行の Range に対して
    書き戻した場合には、同じ行が繰り返し出力されます。

    また、「単一行複数列」を行列変換して「複数行単一列」にするには、
    .PasteSpecial(Transpose:=True) を使うことができますが…
    今回は出番が無さそうですね。


    > Linqを使って変換して、再び上記の形に再変換するしか無いのでしょうか?
    多次元配列用の拡張メソッドを自前で用意してやれば、
    LINQ で処理できるようになります。

    しかし今回のように、配列の一部を置換することを目的とした
    全件走査となると、LINQ のメリットは薄い気がします。
    LINQ を用いたい理由が何かあるのでしょうか?

    クエリ構文の LINQ については、C# より VB の方が充実しているのですが、
    VB のラムダ式は C# のそれに比べて冗長的であるため、VB における
    メソッド構文の LINQ は、他言語のものよりも煩雑になりがちです。


    > 単純に二次元配列をループして一つずつ変換するしか無いのでしょうか?
    質問の意図が良く分かりませんが、それが手っ取り早いと思います。


    > 次のような二次元配列ができました。
    > (1,1) a
    > (2,1) b
    .NET 的には、「添字が 0 から始まる 1 次元配列」であれば、
    パフォーマンスが良いのですが(JIT で特別扱いされる)、このケースだと
    Excel 側の仕様で、1 始まりという特殊な 2 次元配列になってしまうんですよね。

    といっても、COM Interop 呼び出しのボトルネックに比べれば
    微々たる差なので、速度的な問題について気にするほどのものでは無いでしょう。


    > ExcelのRangeのままやった方がいいのかな?
    Excel と通信するたびにプロセス間通信が発生します。

    特にデータ量が多い場合、COM オブジェクトのメソッド呼び出しあるいは
    そのプロパティを読み書きする回数は、最小限にとどめておきましょう。

    処理内容によっては、VBA を使うことも検討してみてください。
    VBA であれば自プロセスとの通信となるため、データ量が多い要件だと、
    VB から操作するよりも早く処理できる可能性があります。

    また、速度面だけが問題の場合には、Excel を経由させることなく
    .xlsx を直接読み書きできるライブラリ(ClosedXml や ReoGrid など)を
    用いた方が処理効率の良いプログラムになります。
    COM オブジェクトの解放処理を気にする必要もなくなりますしね。
違反を報告
引用返信 削除キー/
■34736 / ResNo.2)  Re[2]: 二次元配列内の文字の置き換え
□投稿者/ Wan 一般人(5回)-(2021/05/25(Tue) 17:51:28)
  • アイコン魔界さん。いつも丁寧に有難う御座います。お礼が遅くなり誠に申し訳ありません。
    Excel VBAの関数等を使うということが、プロセス間通信となることは、少し考えればわかる事でしょうが、私の知識では考え付きませんでした。目から鱗です。なるほど、とうなるばかりです。また、Range.Replaceも知りませんでした。
    Application型もそうです。ご指摘通りです。
    何でも間でもVisualStudioから制御すればよいと考えていましたが、最終的には、VBAを使っていることを理解したので、VBAの利用を考えたいと思います。
    拡張メソッドについては、Web上に載っているので、この際、参考までに作っておきたいと思います。
    想像していた、範囲をはるかに超えた情報。いつも助かります。勉強になります。
    有難う御座いました。

違反を報告
引用返信 削除キー/
■34737 / ResNo.3)  解決済みです。
□投稿者/ Wan 一般人(8回)-(2021/05/25(Tue) 17:53:29)
  • アイコン
    解決済み

解決み!
違反を報告
引用返信 削除キー/



スレッド内ページ移動 / << 0 >>

このスレッドに書きこむ

Mode/  Pass/


- Child Tree -