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

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

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

全過去ログを検索

<< 0 >>
■13831  Re[7]: 複数のEXCELファイルのシートを1EXCELのシートに統合
□投稿者/ イナフ -(2008/02/05(Tue) 15:11:57)
    ご返信、誠にありがとう御座います。

    >10ファイルごとに一度保存して終了とかしたら速くなったり
    無念ながら結果を得られませんでした。

    >シートのコピーじゃなく、移動にするとかどうでしょう?
    移動にて処理を行いました。若干早くなりましたが、
    移動を重ねるごとに処理が重くなるのは変わりませんでした。

    > 一度CSVファイルに変換するという手はないのでしょうか?
    CSV形式では表せないデータでしたので、断念致しました。

    統合先のEXCELでシート数が多い場合、コピー、移動処理において時間が掛かかるような感じがします。
    数件毎に統合EXCELを保存して閉じ、再度開いて処理した場合におきましても同様でした。(再度New Excel.Applicationはせず)
    Excel側の処理を軽くしようと考えましたが、値のみならず細かい書式や名前定義なども
    存在し大変ですので、こちらも断念致しました。
    当初便利機能としまして、別アプリで個々に出力されるEXCELを一括して閲覧&ブック単位で一括印刷できるように
    と思い製作しておりました。現在は統合する機能を保留にしまして、フォルダ配下に存在する
    EXCELファイルを一括して印刷するように変更致しました。

    −−−−−−−−−−−−−−−−−−−−−−−−−−−−−
    New Excel.Application
    for XXXX to XXXX
      〜
      '印刷を行う
      xlSheet.PrintOut(From:=1, Copies:=1, Preview:=False)
      〜
    Next
    lApplication.Quit()
    −−−−−−−−−−−−−−−−−−−−−−−−−−−−−

    しかし、このままでは悔しいので時間があるときになんとかしたいと思います。
    皆様本当にありがとう御座いました。一応「解決」にしておきます。

    ※今回参考にしましたURLを貼っておきます。
    http://www.microsoft.com/japan/msdn/office/vsto2003/ExcelObj.aspx#excelobj_link13
記事No.13773 のレス / END /過去ログ29より / 関連記事表示
削除チェック/

■49110  C#からVBAを実行する。
□投稿者/ あきよ -(2010/04/22(Thu) 15:52:51)
>

    分類:[.NET 全般] 

    C#で、フォームからワードのVBAマクロを実行し、戻り値を取得したいと思っております。
    C#側には、
    RunCMacro(oWord, new Object[] { "Project.Module1.WordCount" });

    private void RunCMacro(object oApp, object[] oRunArgs)
    {
    oApp.GetType().InvokeMember("Run",
    System.Reflection.BindingFlags.Default |
    System.Reflection.BindingFlags.InvokeMethod,
    null, oApp, oRunArgs);
    }
    ワード側には、
    Public Static Function WordCount() As Long
    Dim cRes As Long
    cRes = ActiveDocument.ComputeStatistics(Statistic:=wdStatisticWords, IncludeFootnotesAndEndnotes:=True)
    WordCount = cRes

    End Function

    としております。
    ワード側を戻り値のないマクロを指定した場合などには、問題なく動作しております。

    解決方法がありましたら、ご教授下さい。
親記事 /過去ログ83より / 関連記事表示
削除チェック/

■91917  Re[10]: C++からVBへの変換
□投稿者/ 魔界の仮面弁士 -(2019/08/09(Fri) 17:42:02)
    2019/08/13(Tue) 00:01:21 編集(投稿者)

    追記:拡張メソッドの不具合修正

    No91912 (えんえん さん) に返信
    > Dim ar2 As New ArraySegment(Of Double)(ar, r, ar.length - r)
    > が正しいのでしょうか?
    > 要素数を最後まで指定しないといけないですよね?

    そうなりますね。


    処理を分かりやすくするために、ArraySegment のための
    拡張メソッドを用意しておくのが良いでしょう。


    後述のコードを用意しておけば、
      // 元の C++ 実装
      tmpr[m * n_radix + j] = xr * wr - xi * wi;
    に相当する処理を、
      tmpr.SetValue(m * n_radix + j, xr * wr - xi * wi)
    の構文で書ける様になります。


    また、再帰呼び出しの
      // C++
      fft(n_radix, theta * radix, &tmpr[r], &tmpi[r], ar, ai);
    についても、
      fft(n_radix, theta * radix, tmpi.AsSegment(r), tmpi.AsSegment(r), ar, ai)
    で済むようになります。



    '----------------------
    Module ArraySegmentExtension
      <System.Runtime.CompilerServices.Extension>
      Public Function AsSegment(Of T)(this As T()) As ArraySegment(Of T)
        Return New ArraySegment(Of T)(this)
      End Function

      <System.Runtime.CompilerServices.Extension>
      Public Function AsSegment(Of T)(this As T(), start As Integer) As ArraySegment(Of T)
        Return New ArraySegment(Of T)(this, start, this.Length - start)
      End Function

      <System.Runtime.CompilerServices.Extension>
      Public Function AsSegment(Of T)(this As ArraySegment(Of T), start As Integer) As ArraySegment(Of T)
        'Return New ArraySegment(Of T)(this.Array, this.Offset + start, this.ToArray.Length - this.Offset - start)
        Return New ArraySegment(Of T)(this.Array, this.Offset + start, this.Array.Length - this.Offset - start)
      End Function

      <System.Runtime.CompilerServices.Extension>
      Public Function AsSegment(Of T)(this As ArraySegment(Of T), start As Integer, length As Integer) As ArraySegment(Of T)
        Return New ArraySegment(Of T)(this.Array, this.Offset + start, length)
      End Function

      <System.Runtime.CompilerServices.Extension>
      Public Function AsSegment(Of T)(this As T(), start As Integer, length As Integer) As ArraySegment(Of T)
        Return New ArraySegment(Of T)(this, start, length)
      End Function

      <System.Runtime.CompilerServices.Extension>
      Public Function SetValue(Of T)(this As ArraySegment(Of T), index As Integer, newValue As T) As ArraySegment(Of T)
        this.Array(this.Offset + index) = newValue
        Return this
      'End Sub
      End Function
    End Module
記事No.91899 のレス /過去ログ158より / 関連記事表示
削除チェック/

■91938  Re[16]: C++からVBへの変換
□投稿者/ 魔界の仮面弁士 -(2019/08/12(Mon) 12:05:54)
    2019/08/12(Mon) 13:21:00 編集(投稿者)

    No91934 (えんえん さん) に返信
    > 何が間違っていますでしょうか?

    『ステップ実行』しましょう。

    ループ処理などを一行ずつ実行してみた上で、

      この場所では、この変数に
      こういう値がセットされるはずなのに、
      実際にはこんな値になってしまった
     」
    …という点を追跡できれば、どこの翻訳実装に問題があったことが明確になりますよね。


    > とりあえず、先に ArraySegmentを使った方法を試してみました。

    何か所か間違いがありますが、まずはここ。
     tmpr[m * n_radix + j] = xr * wr - xi * wi;

    No91934 のコードでは、上記を
    > tmpr.Array(m * n_radix + j) = xr * wr - xi * wi
    と翻訳してしまっていますので、ここが大きな間違いです。

    たとえば、
     Dim x() As Byte = New Byte(5) {11, 22, 33, 44, 55, 66}
     Dim y As New ArraySegment(Of Byte)(x)
     Dim z As New ArraySegment(Of Byte)(x, 2, 3)
    において、「y.Array」や「z.Array」は、配列 x への参照を意味します。
    ※ Span も似たようなものですが、Span はさらに各要素への参照も持ちます。

    なので、x(3) = 100 と代入すれば、z(1) も同様に 44 から 100 へと変化します。

    この時、それぞれの要素を列挙すれば
     x は {11, 22, 33, 100, 55, 66} 相当 (y.Array や z.Array も同様)
     y は {11, 22, 33, 100, 55, 66} 相当 (y.Offset は 0、y.Count は 6)
     z は {33, 100, 55} 相当 (z.Offset は 2、z.Count は 3)
    となります。
    Array / Offset / Count プロパティの 3 セットが、この構造体の肝です。
    ここまでは良いでしょうか。


    ArraySegment 構造体の場合、値の取得については
     MsgBox( z(i) )
    のように書けるのですが、問題は書き込みです。インデクサが ReadOnly なので、
     z(i) = newValue
    のようには書けません。(Span 構造体なら可能になるはず)

    そのため、オフセット指定の書き込みが必要な場合には、
     z.Array(z.Offset + i) = newValue
    のように、Array プロパティと Offset プロパティを併用することになります。
    No91934 のコードでは、この点が考慮されていないように見受けられます。


    =====

    それと、むやみに ByRef を使わないでください。
    今回は出力引数が存在しないため、ByRef の出番は一切ありません。

    先にも述べましたが、出力引数が必要な場合以外は、値渡しで実装するべきです。



    Sub Main()
      Dim x() As Byte = New Byte(3) {&H11, &H22, &HAB, &HCD}
      MsgBox(BitConverter.ToString(x))

      'AsSegment については No91917 を参照
      Test(x.AsSegment())
      MsgBox(BitConverter.ToString(x))

      Test(x.AsSegment(2, 2))
      MsgBox(BitConverter.ToString(x))
    End Sub

    ' a(0) と a(1) の中身を入れ替える処理
    ' この時、引数 ArraySegment 構造体を ByRef にする必要は無い!
    Sub Test(Of T)(ByVal a As ArraySegment(Of T))
      Dim swap() As T = {a(0), a(1)}
      a.Array(a.Offset + 1) = swap(0)
      a.Array(a.Offset + 0) = swap(1)
    End Sub


    ※ 先の No91917 ですが、最後の End Function が誤って End Sub になっていました。
     恐れ入りますが、 End Function に読み替えておいてください。


    > Public Sub one_D_FFT(ByRef xr#(), ByRef xi#())
    > Private Sub fft(ByVal n%, ByVal theta#, ByRef ar As ArraySegment(Of Double), ByRef ai As ArraySegment(Of Double), ByRef tmpr As ArraySegment(Of Double), ByRef tmpi As ArraySegment(Of Double))

    これらについて、メソッド名を分ける必要は無いと思います。オーバーロードで十分ではないでしょうか。
     Public Sub Fft(xr#(), xi#())
     Private Sub Fft(n%, theta#, ar As ArraySegment(Of Double), ar As ArraySegment(Of Double), tmpr As ArraySegment(Of Double), tmpi As ArraySegment(Of Double))


    メソッド名を分けるにしても、両者でメソッド名の大文字小文字の使い分けが不揃いな点が気にかかります。
    .NET Framework においては一般的に、
      ・クラス名やメソッド名は PascalCase 構文の大文字小文字表記とする。
      ・変数や引数は、camelCase 構文の大文字小文字表記とする。
    というのが一般的ですので、この点を意識したコーディングにされることをお奨めします。
    https://docs.microsoft.com/ja-jp/dotnet/standard/design-guidelines/naming-guidelines
    http://objectclub.jp/community/codingstandard/CodingStdVB.doc
記事No.91899 のレス /過去ログ158より / 関連記事表示
削除チェック/

■91940  Re[18]: C++からVBへの変換
□投稿者/ 魔界の仮面弁士 -(2019/08/12(Mon) 16:25:23)
    No91939 (えんえん さん) に返信
    No91939 (えんえん さん) に返信
    > 以下のようにしてみましたが
    > やはりうまくいきませんでした。

    同じ移植ミスを、他の行でも繰り返していますよ。

    Dim z As ArraySegment(Of T) における、
    z(0) と z.Array(0) の違いをもう一度見直してみましょう。


    >> において、「y.Array」や「z.Array」は、配列 x への参照を意味します。
    >> なので、x(3) = 100 と代入すれば、z(1) も同様に 44 から 100 へと変化します。
    > 「y.Array」や「z.Array」を書き換えた時
    > 元の配列xも同時に変化してくれないといけないのではないのでしょうか?

    はい。ご認識の通り、連動して変化します。
    そして先のそれは「変化することを理解していただくための説明コード」として記載したものです。


    No91938 の説明コードにおいて、読み取り専用の z(1) が x(3) と同じ物であり、
    それが z.Array(z.Offset + 1) を通じて書き換えられることを理解できていれば、
    >>> Dim xr As Double = ar.Array(j)

    >>> xr += (wr0 * ar.Array(r + j) - wi0 * ai.Array(r + j))

    >>> tmpi.Array(m * n_radix + j) = xi * wr + xr * wi

    >>> ai.Array(radix * j + m) = tmpi.Array(n_radix * m + j)
    といったミスをおこさずに済んだかと思います。


    あるいはこの移植ミスが理解不足によるものでもなく、
    単なるうっかりミスだったのであれば、「ステップ実行」して
    配列の内容を確認しながら動作チェックしていれば、
    その間違いに気づけたかもしれません。


    いずれにせよ、毎回、Offset を考慮したコードを書くのは移植ミスを引き起こしやすいので、
    元の C/C++ コードに近い記述にできるよう、何らかのヘルパーメソッドを
    設けることをおすすめしておきます。 No91917 のような拡張メソッドのように。


    > 元の配列xは変化しない方が良いという意味ですか?

    変化させる必要があるからこそ、ArraySegment の利用を提案した次第です。
    変化しないと再帰処理させられないという点は、 No91913 の冒頭でも述べていますね。


    ArraySegment を使わない場合は、御自身で書かれた r_st% のように、
    Offset に相当する引数をそれぞれの配列に対して用意する案が使えます。

    配列が 4 つあるので、本来であれば管理すべき添字も 4 つ分必要ですが、
    今回のケースでは tmp 版か否かで 2 系統あれば十分かと思います。
    (複素数の虚数部と実数部は同じ添字管理で済むため)


    > fftを再帰的に呼び出しているわけですが、
    > この場合、配列を書き換えて元のサブルーチンに返しているわけなので、
    > 参照型である必要があるのではないでしょうか?

    「『参照型』と『値型』の違い」の話と、
    「『参照渡し(ByRef)』と『値渡し(ByVal)』違い」の話が
    まだごっちゃになっているように見えます。


    > もっとも配列の場合、ByValを指定したところで、ByRef扱いになると思いますが
    > 間違っていますか?

    間違っています。


    今回の『void fft(int n, double theta, double ar[], double ai[], double tmpr[], double tmpi[])』において、
    配列部は double* 型のポインタと認識されますが、
     theta = 新しいdouble値;
     ar = 新しいdouble配列を指すポインタ;
     ai = 新しいdouble配列を指すポインタ;
     tmpr = 新しいdouble配列を指すポインタ;
     tmpi = 新しいdouble配列を指すポインタ;
    という処理は一切出てきません。

    あるのは、
     tmpr[何某] = 新しいdouble値;
     tmpi[何某] = 新しいdouble値;
     ar[何某] = 新しいdouble値;
     ai[何某] = 新しいdouble値;
    だけですよね。つまり、これらの引数は「出力引数」ではありません。


    同様に、今回記載された No91939 においても、
    仮引数に対して、新しい配列や ArraySegment を割り当てている個所はどこにもないですよね。
    実引数に対して、新しい配列や ArraySegment を割り当てている個所ならばありますけれども。
記事No.91899 のレス /過去ログ158より / 関連記事表示
削除チェック/

■91946  Re[17]: C++からVBへの変換
□投稿者/ 魔界の仮面弁士 -(2019/08/13(Tue) 01:00:13)
    No91938 (魔界の仮面弁士) に追記
    >  Dim x() As Byte = New Byte(5) {11, 22, 33, 44, 55, 66}
    >  Dim y As New ArraySegment(Of Byte)(x)
    >  Dim z As New ArraySegment(Of Byte)(x, 2, 3)
    > において、「y.Array」や「z.Array」は、配列 x への参照を意味します。
    > なので、x(3) = 100 と代入すれば、z(1) も同様に 44 から 100 へと変化します。

    補足説明。

    System.ArraySegment(Of T) は、.NET Framework 2.0 以上で使用可能な、比較的歴史の長い型ですが、
    「 z(1) 」のようにインデクサで参照するためには、.NET Framework 4.5 以上が必要となります。

    .NET Framework 4 以下の場合、LINQ 操作にさえ対応していないのでご注意ください。




    No91942 (魔界の仮面弁士) に追記
    >> できれば、最終回答をお教えいただけないでしょうか?
    > 申し訳ありませんが、現状は言語文法的な側面からしか回答できません。


    ということで、文法的に変換しただけで、コンパイルすらしていないコードですが、
    一応、当方で翻訳してみたものを掲載してみます。

    C/C++ はそもそも専門外ですし、FFT の理論も全く理解しておらず、おまけに
    どんな値を渡せばよいのか、そしてどういう結果になるべきかというテスト要件すら不明なので、
    およそ「最終回答」と呼ぶには程遠いコードではありますが、一応参考までに。



    'void fft(int n, double theta, double ar[], double ai[], double tmpr[], double tmpi[])
    '{
    Private Sub fft(ByVal n%, ByVal theta#, ByVal ar As ArraySegment(Of Double), ByVal ai As ArraySegment(Of Double), ByVal tmpr As ArraySegment(Of Double), ByVal tmpi As ArraySegment(Of Double))

      'if (n <= 1) return;
      If n <= 1 Then Exit Sub

      '/* ---- factorization ---- */
      'for (radix = 2; radix * radix <= n; radix++) {
      '  if (n % radix == 0) break;
      '}
      Dim radix As Integer = 2
      Do While radix * radix <= n
        If n Mod radix = 0 Then Exit Do
        radix += 1
      Loop

      'if (n % radix != 0) radix = n;
      'n_radix = n / radix;
      If n Mod radix <> 0 Then radix = n
      Dim n_radix As Integer = n \ radix

      '/* ---- butterflies ---- */
      'for (j = 0; j < n_radix; j++) {
      '  for (m = 0; m < radix; m++) {
      For j As Integer = 0 To n_radix - 1
        For m As Integer = 0 To radix - 1

          'xr = ar[j];
          'xi = ai[j];
          '==> ここから修正案の新コード
          Dim xr As Double = ar(j)
          Dim xi As Double = ai(j)
          '=== ここから No91939 の旧コード
          'Dim xr As Double = ar.Array(j)
          'Dim xi As Double = ai.Array(j)
          '<==


          'for (r = n_radix; r < n; r += n_radix) {
          For r As Integer = n_radix To n - 1 Step n_radix

            'wr = cos(theta * m * r);
            'wi = sin(theta * m * r);
            Dim wr0 As Double = Math.Cos(theta * m * r)
            Dim wi0 As Double = Math.Sin(theta * m * r)

            'xr += wr * ar[r + j] - wi * ai[r + j];
            'xi += wr * ai[r + j] + wi * ar[r + j];
            '==> ここから修正案の新コード
            xr += wr0 * ar(r + j) - wi0 * ai(r + j)
            xi += wr0 * ai(r + j) + wi0 * ar(r + j)
            '=== ここから No91939 の旧コード
            xr += wr0 * ar.Array(r + j) - wi0 * ai.Array(r + j)
            xi += wr0 * ai.Array(r + j) + wi0 * ar.Array(r + j)
            '<==

          '}
          Next r

          'wr = cos(theta * m * j);
          'wi = sin(theta * m * j);
          Dim wr As Double = Math.Cos(theta * m * j)
          Dim wi As Double = Math.Sin(theta * m * j)

          'tmpr[m * n_radix + j] = xr * wr - xi * wi;
          'tmpi[m * n_radix + j] = xi * wr + xr * wi;
          tmpr.Array(tmpr.Offset + m * n_radix + j) = xr * wr - xi * wi
          tmpi.Array(tmpi.Offset + m * n_radix + j) = xi * wr + xr * wi

        '}
        Next m

      '}
      Next j


      'for (r = 0; r < n; r += n_radix) {
      '  fft(n_radix, theta * radix, &tmpr[r], &tmpi[r], ar, ai);
      '}
      For r As Integer = 0 To n - 1 Step n_radix
        '==> ここから修正案の新コード (要 No91917 の拡張メソッド)
        fft(n_radix, theta * radix, tmpr.AsSegment(r), tmpi.AsSegment(r), ar, ai)
        '=== ここから No91939 の旧コード
        fft(n_radix, theta * radix, New ArraySegment(Of Double)(tmpr.Array, tmpr.Offset + r, tmpr.Count - r), New ArraySegment(Of Double)(tmpi.Array, tmpi.Offset + r, tmpi.Count - r), ar, ai)
        '<==
      Next r

      'for (j = 0; j < n_radix; j++) {
      '  for (m = 0; m < radix; m++) {
      '    ar[radix * j + m] = tmpr[n_radix * m + j];
      '    ai[radix * j + m] = tmpi[n_radix * m + j];
      '  }
      '}
      For j As Integer = 0 To n_radix - 1
        For m As Integer = 0 To radix - 1
          '==> ここから修正案の新コード (要 No91917 の拡張メソッド)
          ar.SetValue( radix * j + m, tmpr(n_radix * m + j) )
          ai.SetValue( radix * j + m, tmpi(n_radix * m + j) )
          '=== ここから No91939 の旧コード
          ar.Array(ar.Offset + radix * j + m) = tmpr.Array(n_radix * m + j)
          ai.Array(ai.Offset + radix * j + m) = tmpi.Array(n_radix * m + j)
          '<==
        Next m
      Next j

    '}
    End Sub
記事No.91899 のレス /過去ログ158より / 関連記事表示
削除チェック/



<< 0 >>

パスワード/

- Child Tree -