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

■ 「新規作成」から投稿できます。
■ マルチポストされた投稿を見つけたときは、その投稿に返信することによりご報告ください。その際は匿名で投稿し、マルチポストされている場所を併記してください。
■ スパム対策のため、メールアドレスの先頭に"_"という文字が付加されています。
RSS 2.0 RSS 2.0 | RSS 0.91 | 携帯電話用 | 自分専用のアイコンを使用するには | 掲示板への要望 | 管理人に連絡 | お気楽掲示板
■ 24時間以内に作成されたスレッドは New で表示されます。
■ 24時間以内に更新されたスレッドは UpDate で表示されます。

記事リスト ( )内の数字はレス数
Nomalフォントに登録されていない文字の検出(1) | Nomaloledbでdatatableを取得するときにエラーになる(1) | NomalDataGridViewの複数行選択で歯抜け選択を無効にしたい(2) | Nomal証券会社へのログイン(1) | Nomalユーザーフォームに埋め込んだAutoCADの変化を捉える(0) | Nomalシステムドライブ以外へのページング設定が反映されない(5) | Nomalブラウザでコピーした透過PNGを貼り付けたい(4) | Nomalforeachでループ回数を取得(2) | Nomalbitmapが保存できない(2) | Nomal特定ピクセルで画像を読み込みたい(2) | NomalDataGridViewでAlt+Enterで改行したい(2) | Nomal全角シフト中にアクセスキーが効かない(5) | NomalDataAdapter.Updateで構文エラー(6) | Nomal抽象クラスで実装したクラスの情報を知る(3) | NomalProcessクラスからbatファイル実行後、KILLできない(2) | Nomal画面遷移(モーダルとモードレス)(2) | Nomal兆億万表記の文字列を数値に変換できる?(3) | NomalGetDirectoriesでルートを指定するとエラーになる(3) | NomalLinqにおける明示的型指定の方法(3) | Nomal2つのradの数値から1つの角度を求めるコードを改善できますか?(C++)(2) | Nomalコンソールアプリで、WebView2の利用(2) | NomalEntity Frameworkは、使えるか?(2) | Nomalデータベースからのテーブル名一覧の効率的な取得方法(3) | NomalC#のlong型でオーバーフローになる(2) | Nomal正規表現のパターン表記方法(2) | NomalWebView2によるスクレ―ピング(4) | Nomalこういた物を作れますか?(2) | Nomalツールボックスにtableadapterが表示されない(1) | NomalC# Chart X軸上のグラフ表示(3) | NomalVB.NETでBluetoothデバイスの電池残量を取得する方法(3) | Nomalクリスタルレポート 明細部のサブレポート(0) | Nomal重なったPictureBox同士を透過する方法(7) | NomalWindowsフォームデザイナについて(3) | NomalVB.NETからcmdでpingを実行した時の結果(5) | Nomalvb.netでExcelファイル操作(7) | Nomalvb.netでのExcelファイルそうさ(2) | Nomalキーボード+バーコードでキーボード入力を無効にしたい(6) | Nomalファイルとして配置したマニフェストを優先したい(2) | NomalTabPageの背景色(5) | NomalVB2022でクリスタルレポートが開けない(2) | NomalC#でJpeg圧縮のTiffファイルを作成したい(4) | Nomalエクセルのみ監視ができない(2) | NomalDataGridViewのVirtualModeを有効した場合の実装方法(4) | NomalExcelの数値 -> 日付みたいな関数?(2) | NomalDrawstringでの透過文字作成(3) | Nomaljumbo icon(256x256)が存在するか知る方法(6) | NomalSpinWait()を使う理由(2) | Nomalantecedentってなんですか?(2) | Nomalワンタイムパスワードのサイトに自動ログインしてアクセストークンを得る(3) | Nomalstyle.displayだと効率悪いから違うやり方をしたいです。(5) | Nomalテーブルを順番通りに直すプログラムを外部で読み込めるようにしたいです。(4) | NomalJSONの複雑な入れ子内部の値を取りたい。(3) | Nomalグリッド表示レコードをJSONに変換(5) | Nomalシステム時計の設定(3) | NomalSeleniumで開いているページのTableを編集したい(5) | Nomalソケット通信入門 ひらがな(4) | NomalVisual Basicでエラーが出る(3) | Nomalインストーラにて、ローミングフォルダにファイルを配置したい(0) | NomalRGB値の所得(2) | NomalVB.net からAccessDBへの接続(2) | Nomal時間変数(文字列)の扱い(4) | Nomal画像のスクロール(6) | Nomalタイマーの一括処理(6) | NomalTreeViewとDataGridViewのスクロールを同期(シンクロ)させたい(4) | NomalTreeViewの現在位置とDataGridViewの現在位置を合わせたい(7) | Nomalフォームのリサイズ時にDataGridViewが再描画されない(4) | NomalPDFをフォーム上で表示させる方法につきまして(4) | NomalPictureBoxの画像を連続保存(11) | NomalテキストボックスのValidatingイベントよりも先に発生するボタン発生イベントは何でしょう?(2) | Nomal継承元フォームで各フォームのボタン動作を検知したい(3) | NomalWindowsエクスプローラからのドラッグ&ドロップ(2) | Nomalラジオボタンの一括設定(7) | Nomalクリックイベントでexeを作成できるか(2) | Nomal作成した白黒画像をWordに貼り付けてから「図として保存」(8) | Nomalアセンブリ情報が載らない(1) | NomalRichTextBoxのテキストをpictureBOXへ(12) | Nomalc#で日付型の定義の仕方で質問があります。(2) | Nomal先頭に空白(スペース)があるファイルを読み込んでRichTextBoxへ書き出すとスペースが削除える(6) | NomalExcel Com オブジェクトの増殖(13) | Nomal二次元マップから値の取得(1) | NomalアプリでHDMIへ出す解像度を変えたい(4) | NomalDataGridViewのドロップダウンリストの表示と選択後の値を分けたい(1) | Nomal列車の時間ごとの位置情報を表示したいです。(2) | Nomal画像の中心を基点に回転(4) | NomalDataGridViewの行ヘッダーに行番号を表示した時のエラー(4) | NomalタッチキーボードでIMEを自動で切替えたい(6) | NomalVSTOによるエクセルアドインのインストーラーでのアップデート(1) | NomalMP4動画を再生する方法について(5) | NomalVB.NetでVB6.0と同じFontを指定しても同様に印刷されない(9) | NomalLabelで文字単位の背景色(7) | NomalLableのカラー色を文字変数から変更したい(5) | NomalUrlにアクセスするとダウンロードされるファイルを捕まえる(2) | Nomalタブレット等でスワイプによるスクロールを実装(2) | NomalTEXTBOXのプロパティを文字列に(7) | NomalPDFをフォーム上で表示させる方法につきまして(6) | NomalChart X軸上の描画を切り替えたい(0) | NomalRichTextBoxへのドラッグ&ドロップしたExcelファイルの扱い(3) | Nomal特定のPCだけ発生する「パディングは無効なので削除できません」のエラーの原因(6) | NomalDataGridViewの特定セルにボタンを配置する方法(5) |



■記事リスト / ▼下のスレッド
■35270 / 親記事)  RichTextBoxのテキストをpictureBOXへ
□投稿者/ ま〜 一般人(28回)-(2022/12/05(Mon) 15:45:30)
  • アイコン環境/言語:[Windows10 VS2022 Basic] 
    分類:[.NET] 

    こんにちは
    以前、
    https://dobon.net/cgi-bin/vbbbs/cbbs.cgi?mode=al2&namber=35233&rev=&no=0
    でLEDモニタの件で画像にすればと提案頂いて格闘していましたが玉砕気味です。
    現状は
    Dim img As Bitmap
    img = New Bitmap(Me.RichTextBox1.Width, Me.RichTextBox1.Height)
    Using g As Graphics = Graphics.FromImage(img)
    g.CopyFromScreen(Me.PointToScreen(Me.RichTextBox1.Location), New Point(0, 0), Me.RichTextBox1.Size)
    End Using
    Me.PictureBox1.Image = img

    です。転送はて来たのですがRichTextBoxの位置情報が上手く取れずに少しずれてしまいます。
    Me.RichTextBox1.Locationの値が連想出来ない数値になってます。
    色々やってみましたが私のコピペ専門の理解度では難しく教えて下さい
    初歩的な質問で申し訳ないですが宜しくお願いします






違反を報告
引用返信

▽[全レス12件(ResNo.8-12 表示)]
■35279 / ResNo.8)  Re[6]: RichTextBoxのテキストをpictureBOXへ
□投稿者/ KOZ 一般人(11回)-(2022/12/08(Thu) 18:38:13)
  • アイコン
    2022/12/09(Fri) 04:27:45 編集(投稿者)
    
    ■No35275に返信(ま〜さんの記事)
    >>高 DPI 環境で実行している場合は、ズレる可能性がありますね。
    > まさにこれが原因でした。凄いです感激です。
    
    これ動きますか?
    ちょっと問題があって、画像を縮小するせいか、少しぼやけた感じになります。
    ,NET Framework 4.7 以上なら RichTextBox の DrawToBitmap を使ったほうがいいかもしれません。
    
    Imports System.Runtime.InteropServices
    
    Public Class Form1
    
        <DllImport("User32.dll")>
        Public Shared Function LogicalToPhysicalPointForPerMonitorDPI(ByVal hwnd As IntPtr, ByRef point As Point) As Boolean
        End Function
    
        Private Shared Function LogicalToPhysicalRectangleForPerMonitorDPI(ByVal hwnd As IntPtr, ByVal r As Rectangle) As Rectangle
            Dim p1 As Point = r.Location
            Dim p2 As Point = New Point(r.Right, r.Bottom)
            LogicalToPhysicalPointForPerMonitorDPI(hwnd, p1)
            LogicalToPhysicalPointForPerMonitorDPI(hwnd, p2)
            Return Rectangle.FromLTRB(p1.X, p1.Y, p2.X, p2.Y)
        End Function
    
        Private Function LogicalToPhysicalRectangleForPerMonitorDPI(ByVal r As Rectangle) As Rectangle
            Return LogicalToPhysicalRectangleForPerMonitorDPI(Handle, r)
        End Function
    
        Public Sub New()
            InitializeComponent()
            PictureBox1.SizeMode = PictureBoxSizeMode.Zoom
            PictureBox1.Size = RichTextBox1.Size
        End Sub
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Dim rectangle1 = RectangleToScreen(RichTextBox1.Bounds)
            Dim rectangle2 = LogicalToPhysicalRectangleForPerMonitorDPI(rectangle1)
            Dim bmp = New Bitmap(rectangle2.Width, rectangle2.Height)
            Using g = Graphics.FromImage(bmp)
                g.CopyFromScreen(rectangle2.Location, Point.Empty, rectangle2.Size)
            End Using
            If PictureBox1.Image IsNot Nothing Then
                PictureBox1.Image.Dispose()
            End If
            PictureBox1.Image = bmp
        End Sub
    
    End Class
    

違反を報告
引用返信
■35280 / ResNo.9)  Re[7]: RichTextBoxのテキストをpictureBOXへ
□投稿者/ ま〜 一般人(31回)-(2022/12/15(Thu) 13:11:41)
  • アイコンこんにちは、体調を崩して回答が遅れました。すみません。
    ご指導の様にやってみました。DPI環境でもバッチリでした。
    ありがとうございます

    ですがTabPage環境化ではズレました。
    Parentをと思って色々やってみましたが中々上手くいかずTabPage下の座標知る方法はないのでしょうか?
    以上、宜しくお願いします

違反を報告
引用返信
■35282 / ResNo.10)  Re[8]: RichTextBoxのテキストをpictureBOXへ
□投稿者/ KOZ 一般人(12回)-(2022/12/15(Thu) 18:00:28)
  • アイコン
    No35280に返信(ま〜さんの記事)
    > こんにちは、体調を崩して回答が遅れました。すみません。
    
    お大事に。
    
    > ですがTabPage環境化ではズレました。
    > Parentをと思って色々やってみましたが中々上手くいかずTabPage下の座標知る方法はないのでしょうか?
    
    むむむ、やっかいですね高DPI。
    スクリーン座標を取るのが目的でないなら、以下のコードでキャプチャはできると思います。
    
    Imports System.Runtime.InteropServices
    
    Public Class Form1
    
        Public Sub New()
            InitializeComponent()
            PictureBox1.SizeMode = PictureBoxSizeMode.Zoom
            PictureBox1.Size = RichTextBox1.Size
        End Sub
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Dim bmp = CreateBitmapFromControl(RichTextBox1)
            If PictureBox1.Image IsNot Nothing Then
                PictureBox1.Image.Dispose()
            End If
            PictureBox1.Image = bmp
        End Sub
    
        Private Const SRCCOPY As Integer = &HCC0020
    
        <DllImport("User32.dll")>
        Private Shared Function GetWindowDC(hWnd As IntPtr) As IntPtr
        End Function
    
        <DllImport("user32.dll")>
        Private Shared Function ReleaseDC(hWnd As IntPtr, hDC As IntPtr) As Boolean
        End Function
    
        <DllImport("gdi32.dll")>
        Private Shared Function BitBlt(hdcDest As IntPtr,
                                       nXDest As Integer, nYDest As Integer,
                                       nWidth As Integer, nHeight As Integer,
                                       hdcSrc As IntPtr,
                                       nXSrc As Integer, nYSrc As Integer,
                                       dwRop As Integer) As Boolean
        End Function
    
        Private Shared Function CreateBitmapFromControl(con As Control) As Bitmap
            Dim cs = con.Size
            Dim bmp As New Bitmap(cs.Width, cs.Height)
            Using g = Graphics.FromImage(bmp)
                Dim hdcDest = g.GetHdc()
                Dim hdcSrc = GetWindowDC(con.Handle)
                BitBlt(hdcDest, 0, 0, cs.Width, cs.Height, hdcSrc, 0, 0, SRCCOPY)
                ReleaseDC(con.Handle, hdcSrc)
                g.ReleaseHdc()
            End Using
            Return bmp
        End Function
    
    End Class
    

違反を報告
引用返信
■35295 / ResNo.11)  Re[9]: RichTextBoxのテキストをpictureBOXへ
□投稿者/ ま〜 一般人(32回)-(2022/12/19(Mon) 13:37:36)
  • アイコンPCを変えたりし確認しました。
    バッチリです。
    沢山勉強になりました。
    ありがとうございます。
違反を報告
引用返信
■35296 / ResNo.12)  Re[10]: RichTextBoxのテキストをpictureBOXへ
□投稿者/ ま〜 一般人(33回)-(2022/12/19(Mon) 13:45:34)
  • アイコンクローズ忘れてました。
解決み!
違反を報告
引用返信

■記事リスト / レス記事表示 → [親記事-9] [10-12]



■記事リスト / ▼下のスレッド / ▲上のスレッド
■35266 / 親記事)  c#で日付型の定義の仕方で質問があります。
□投稿者/ sun 一般人(1回)-(2022/12/02(Fri) 15:58:32)
  • アイコン環境/言語:[C#] 
    分類:[.NET] 

    はじめまして。
    C#でプログラムを組むことになったのですが、よくわからない定義の仕方がありまして、ググったのですが分かりませんでした。
    どなたかおしえていただけないでしょうか?

    下記の?の意味が分からなくて。
     public decimal? id;
     public DateTime? edate;



違反を報告
引用返信

▽[全レス2件(ResNo.1-2 表示)]
■35267 / ResNo.1)  Re[1]: c#で日付型の定義の仕方で質問があります。
□投稿者/ 魔界の仮面弁士 大御所(1497回)-(2022/12/02(Fri) 17:03:40)
  • アイコン2022/12/02(Fri) 23:51:36 編集(投稿者)

    No35266に返信(sunさんの記事)
    > 下記の?の意味が分からなくて。
    >  public decimal? id;
    >  public DateTime? edate;
    これらは
     public Nullable<decimal> id;
     public Nullable<DateTime> edate;
    の省略表記です。
    こうしたデータ型は「null 許容値型」と呼ばれます。


    string や Form などは「クラス」です。
    クラスは「参照型」であり、default 値は null です。

    decimal や int や bool や DateTime は「構造体」です。
    構造体は「値型」であり、default 値はゼロです。

    そして構造体には null をセットできません。

    string a = default(string); // string a = null; と同義
    int b = default(int); // int b = 0; と同義
    bool c = default(bool); // bool c = false; と同義

    しかし Nullable<T> すなわち T? 型にすると、null が許容されます。

    int? x = null; // 0 とは異なる
    int? y = 123;
    int? z = x + y;

    たとえば bool 型は、true と false の二値のみの型ですが、
    bool? 型にすれば、true と false と null の三値を持てることになります。


    > C#でプログラムを組むことになったのですが、
    「C#」ではなく、
    「C#」と書いた方が良いでしょう。


    日本工業規格 JIS X 3015 "プログラミング言語C#"
    →序文 6 [頭字語及び略語]
    》 箇条6は,参考であって,規定ではない。
    (中略)
    》 C#は,“しーしゃーぷ”と発音する。
    》 C#は,LATIN CAPITAL LETTER C (U+0043)の次にNUMBER SIGN # (U+0023)を書く。

    ECMA-334 "C# Language Specification"
    ISO/IEC 23270:2006 "Information technology -- Programming languages -- C#"
    →Introduction 6. [Acronyms and abbreviations]
    》 The name C# is pronounced “C Sharp”.
    》 The name C# is written as the LATIN CAPITAL LETTER C (U+0043) followed by the NUMBER SIGN # (U+0023).
違反を報告
引用返信
■35268 / ResNo.2)  Re[2]: c#で日付型の定義の仕方で質問があります。
□投稿者/ sun 一般人(2回)-(2022/12/02(Fri) 20:17:34)
  • アイコンこういう書き方があるの初めて知りました。

    どういう時に使用すると有益なのか、これからいろいろと書いてみて経験していきたいと思います。

    C#も記載の仕方気をつけます。

    ありがとうございました。

解決み!
違反を報告
引用返信

■記事リスト / レス記事表示 → [親記事-2]



■記事リスト / ▼下のスレッド / ▲上のスレッド
■35259 / 親記事)  先頭に空白(スペース)があるファイルを読み込んでRichTextBoxへ書き出すとスペースが削除える
□投稿者/ ま〜 一般人(23回)-(2022/12/01(Thu) 13:34:12)
  • アイコン環境/言語:[Windows10 VS20222] 
    分類:[.NET] 

    いつもありがとうございます。またハマってます。

    例)" 1 2345"の文字列
       ↑スペース
      
    テキストファイルの内容に先頭にスペースがあるファイルを読み込んでRichTextBoxへ書き出すと先頭のスペース全部が削除されます
    "1 2345こんな感じになります。"
    間にある(1と2間)スースは消えません。
    何がダメなのか分からない状況です。

    Dim sr As Microsoft.VisualBasic.FileIO.TextFieldParser = New Microsoft.VisualBasic.FileIO.TextFieldParser (DataPath & "文字.TXT", System.Text.Encoding.GetEncoding("shift_jis"))

    '内容は区切り文字形式
    sr.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited

    'デリミタはカンマ
    sr.SetDelimiters(",")

    Dim Row As String() '= sr.ReadFields
    '一行目を読み込
    Row = sr.ReadFields()
    RichTextBox1.Text = Row(0)
    Console.WriteLine(Row(0))

    上記の様にやってます。アドバイスお願いします。
違反を報告
引用返信

▽[全レス6件(ResNo.2-6 表示)]
■35261 / ResNo.2)  Re[1]: 先頭に空白(スペース)があるファイルを読み込んでRichTextBoxへ書き出すとスペースが削除える
□投稿者/ KOZ 一般人(7回)-(2022/12/01(Thu) 14:19:47)
  • アイコンNo35259に返信(ま〜さんの記事)
    > テキストファイルの内容に先頭にスペースがあるファイルを読み込んでRichTextBoxへ書き出すと先頭のスペース全部が削除されます

    こういうふうに書くということは、どこでスペースが削除されているのか、調べていないということですか?
    せめて原因がどこにあるか突き止めてから書き込みましょう。
    RichTextBox は関係ないですよね?

    「TextFieldParser.TrimWhiteSpace プロパティ」
    https://learn.microsoft.com/ja-jp/dotnet/api/microsoft.visualbasic.fileio.textfieldparser.trimwhitespace?view=netframework-4.8
    を False にしてください。

違反を報告
引用返信
■35263 / ResNo.3)  Re[1]: 先頭に空白(スペース)があるファイルを読み込んでRichTextBoxへ書き出すとスペースが削除える
□投稿者/ 魔界の仮面弁士 大御所(1496回)-(2022/12/01(Thu) 14:39:24)
  • アイコンNo35259に返信(ま〜さんの記事)
    > テキストファイルの内容に先頭にスペースがあるファイルを読み込んで
    > RichTextBoxへ書き出すと先頭のスペース全部が削除されます
    どこまで調査されましたか?

    その事象は、RichTextBox の問題なのでしょうか。
    テキストファイル読み取りの問題なのでしょうか。


    > RichTextBox1.Text = Row(0)
    この時、Row(0) の先頭に空白が含まれているかどうかを確認済みでしょうか?


    Row(0) の先頭に空白が既に含まれていたのであれば、
    「先頭に空白があるファイル」の読み込みは成功していて
    「RichTextBoxへ書き出すとスペースが削除される」という状況といえるでしょう。

    その場合、質問時に TextFieldParser に関するくだりを述べる必要はなく、
    単純に「RichTextBox1.Text = " 1 2345"」に関する動作を示すだけで良いはず。


    一方、Row(0) の時点で先頭空白が失われてしまう状況なのであれば、
    RichTextBox は一切関係ないことになります。その場合はファイルの
    読み込み手順によるもの(TextFieldParser を使うことの是非)でないかを調べたり
    ファイル内容に問題が無いか(空白に見えるが、実は別の不可視文字だったとか)を
    調べることになりますよね。場合によっては、
     RichTextBox1.LoadFile(DataPath & "文字.TXT", RichTextBoxStreamType.PlainText)
    の結果と比較してみても良いかもしれません。


    > 上記の様にやってます。アドバイスお願いします。
    結論から言えば、TextFieldParser が原因です。
    このクラスは先頭末尾空白を自動的に削除しますし、
    改行のみの行(いわゆる空行)も無視する仕様です。

    先頭末尾空白については TrimWhiteSpace プロパティで抑制できますが
    空行無視は回避策がなかったはずなので、要件次第では
    TextFieldParser 以外の選択肢を検討した方が良いかと思います。
違反を報告
引用返信
■35264 / ResNo.4)  Re[2]: 先頭に空白(スペース)があるファイルを読み込んでRichTextBoxへ書き出すとスペースが削除える
□投稿者/ ま〜 一般人(26回)-(2022/12/01(Thu) 14:55:09)
  • アイコンKOZさん魔界さんありがとうございます

    ご指摘の様にRichTextBoxは関係無くファイルから変数に読み込んだ段階で消えています。
    仕様なんですね。なんか私にはハードルが高くなってきました。

違反を報告
引用返信
■35265 / ResNo.5)  Re[3]: 先頭に空白(スペース)があるファイルを読み込んでRichTextBoxへ書き出すとスペースが削除える
□投稿者/ KOZ 一般人(8回)-(2022/12/01(Thu) 16:43:39)
  • アイコンNo35264に返信(ま〜さんの記事)
    > KOZさん魔界さんありがとうございます

    「魔界さん」ではなく、「弁士さん」と呼びましょう。
    # 遠い昔、本人がおっしゃってたので(^_^;)

    > ご指摘の様にRichTextBoxは関係無くファイルから変数に読み込んだ段階で消えています。
    > 仕様なんですね。なんか私にはハードルが高くなってきました。

    弁士さんが書いてらっしゃいますが要件次第です。
    項目に改行がない、空行を無視して良いなら TextFieldParser で充分かと。

違反を報告
引用返信
■35269 / ResNo.6)  Re[4]: 先頭に空白(スペース)があるファイルを読み込んでRichTextBoxへ書き出すとスペースが削除える
□投稿者/ ま〜 一般人(27回)-(2022/12/05(Mon) 15:33:41)
  • アイコン出来ました。
    ありがとうございます。
解決み!
違反を報告
引用返信

■記事リスト / レス記事表示 → [親記事-6]



■記事リスト / ▼下のスレッド / ▲上のスレッド
■35241 / 親記事)  Excel Com オブジェクトの増殖
□投稿者/ たこ 一般人(15回)-(2022/11/27(Sun) 04:14:52)
  • アイコン環境/言語:[[Windows10 VB.NET .NET Framework 4.7.2 VS2019]] 
    分類:[.NET] 

    環境追記
    [Office 365 Excel バージョン2210]
    [Microsoft Excel 16.0 Object Library]


    いつもお世話になっております。

    今回Excelの既存データをまとめようと思いまして、
    VB.NETのExcel Comオブジェクトを使用して2枚のExcelを開いて処理しています。

    Excelの処理部分はクラスにまとめ処理していますが、タスクマネージャーで見ると閉じたはずのExcelが残っています。
    いろいろやってみましたが解決できず、お知恵をお借りしたいと投稿致します。


    <参考にしたサイト>
    https://hironimo.com/prog/vbnet/vb-net-excel/
    https://oreno-it2.info/archives/1043
    http://vbnettips.blog.shinobi.jp/file-folder/excel%20%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E6%93%8D%E4%BD%9C%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%EF%BC%88microsof
    http://hanatyan.sakura.ne.jp/vb2005/vb2013excel01.htm
    http://up-up-everyday.cocolog-nifty.com/wanco_programming/2015/07/vbnetexcel-81a4.html


    ExcelExクラス(抜粋)
    ----------------------------------------------------------------------------------------------------
      'Excel のアプリケーション参照用オブジェクト
      Friend xlsApplication As Excel.Application = Nothing
      'Excel の Workbooks 参照用オブジェクト (Workbook の Collection)
      Friend xlsWorkbooks As Excel.Workbooks = Nothing
      'Excel の Workbooks 内の1個の Workbook 参照用オブジェクト
      Friend xlsWorkbook As Excel.Workbook = Nothing
      'Excel の Workbook 内の Worksheets 参照用オブジェクト (Worksheet の Collection)
      Friend xlsWorkSheets As Excel.Sheets = Nothing
      'Excel の Sheets 内の1個の Worksheet 参照用オブジェクト
      Friend xlsWorkSheet As Excel.Worksheet = Nothing
      'Excel の Sheet 内の1個のセル Range 参照用オブジェクト
      Friend xlsRange As Excel.Range = Nothing

      Private _WorkBook As String = Nothing
      Private _WorkBookIsNew As Boolean = Nothing
      Public Property WorkBook As String
        Set(value As String)
          _WorkBook = value
          Select Case _WorkBook
            Case ""
              WorkBook_Open()
              _WorkBookIsNew = True
            Case "Close"
              _frgClose = True
              WorkBook_Close()
            Case "Save"
              xlsWorkbook.Save()
            Case "SaveAfterClose", "CloseBeforeSave"
              xlsWorkbook.Save()
              _frgClose = True
              WorkBook_Close()
            Case Else
              WorkBook_Open(_WorkBook)
              _WorkBookIsNew = False
          End Select
        End Set
        Get
          Return _WorkBook
        End Get
      End Property

      Private Sub WorkBook_Open(Optional ByVal strFileName As String = Nothing)
        'Excel アプリケーション起動
        xlsApplication = New Excel.Application
        'Excel の Workbooks 取得
        xlsWorkbooks = xlsApplication.Workbooks
        'Excel非表示
        xlsApplication.Visible = False
        xlsApplication.DisplayAlerts = False
        If IsNothing(strFileName) Then
          '新規 Excel ファイルを開く
          xlsWorkbook = xlsWorkbooks.Add()
        Else
          '既存 Excel ファイルを開く
          xlsWorkbook = xlsWorkbooks.Open(strFileName)
        End If
        'Excel の Worksheets 取得
        xlsWorkSheets = xlsWorkbook.Worksheets
        'Excel の Worksheet 取得
        xlsWorkSheet = xlsWorkSheets.Item(1)
        xlsWorkSheet.Select()
        xlsApplication.Visible = ExcelVisible
      End Sub

      Private Sub WorkBook_Close()
        '終了処理
        'xlsRange の解放
        MRComObject(xlsRange, True)
        'xlsWorkSheet の解放
        MRComObject(xlsWorkSheet, True)
        'xlsWorkSheets の解放
        MRComObject(xlsWorkSheets, True)
        'xlsWorkbookを閉じる
        If Not xlsWorkbook Is Nothing Then xlsWorkbook.Close()
        'xlsWorkbook の解放
        MRComObject(xlsWorkbook, True)
        'xlsWorkbooks の解放
        MRComObject(xlsWorkbooks, True)
        'Excelを閉じる
        If Not xlsApplication Is Nothing Then xlsApplication.Quit()
        'xlsApplication を解放
        MRComObject(xlsApplication, True)
      End Sub

      'COM オブジェクトへの参照を解放
      ''' <summary>
      ''' COMオブジェクトの参照カウントをデクリメントします。
      ''' </summary>
      ''' <typeparam name="T">(省略可能)</typeparam>
      ''' <param name="objCom">
      ''' COM オブジェクト持った変数を指定します。
      ''' このメソッドの呼出し後、この引数の内容は Nothing となります。
      ''' </param>
      ''' <param name="force">
      ''' すべての参照を強制解放する場合はTrue、現在の参照のみを減ずる場合はFalse。
      ''' </param>
      Friend Sub MRComObject(Of T As Class)(ByRef objCom As T, Optional ByVal force As Boolean = False)
        If objCom Is Nothing Then Return
        Try
          If System.Runtime.InteropServices.Marshal.IsComObject(objCom) Then
            If force Then
              System.Runtime.InteropServices.Marshal.FinalReleaseComObject(objCom)
            Else
              System.Runtime.InteropServices.Marshal.ReleaseComObject(objCom)
            End If
          End If
        Finally
          objCom = Nothing
        End Try
      End Sub
    ----------------------------------------------------------------------------------------------------

    上記ExcelExクラスがベースクラスで、子クラス、孫クラスがあります。
    子クラスで、Data As Microsoft.Office.Interop.Excel.Rangeと言うヶ所があるので、
    (必要無いとは思っているものの)MRComObject(Data)と入れてあります。

    ちょっと書いている途中で思いついたので、ベースクラスのみ呼び出して閉じる…
    ----------------------------------------------------------------------------------------------------
      Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        ExEx1 = New ExcelEx()
        ExEx1.WorkBook = path & "Test.xlsx"
        ExEx1.xlsApplication.WindowState = Excel.XlWindowState.xlMaximized
        ExEx1.Sheets(1)
        ExEx1.WorkBook = "Close"
      End Sub
    ----------------------------------------------------------------------------------------------------
    を実行してもやはりゴミが残ります。

    Excelを閉じた時にプロセスは終了・削除されると思っているのですが、認識が違うのでしょうか…

違反を報告
引用返信

▽[全レス13件(ResNo.9-13 表示)]
■35253 / ResNo.9)  Re[6]: Excel Com オブジェクトの増殖
□投稿者/ 魔界の仮面弁士 大御所(1492回)-(2022/11/27(Sun) 22:56:50)
  • アイコンNo35251に返信(たこさんの記事)
    > Dim check As Boolean = False
    > For Each sh In xlsSheets
    >   If CType(sh, Excel.Worksheet).Name = strSheetName Then
    >     check = True
    >     Exit For
    >   End If
    > Next

    ここがマズイですね。
    MRComObject(sh) が明らかに漏れています。


    また、 No35252 でも紹介したように、COM オブジェクトに対して For Each を使うと、
    System.Runtime.InteropServices.ComTypes.IEnumVARIANT インターフェイス
    (を実装した EnumeratorViewOfEnumVariant クラス) の解放を行うことが難しくなるので
    For ループ または Do ループ あるいは While ループ に置き換えることをお奨めします。



    > Private _ExcelVisible As Boolean = True
    > Friend Property ExcelVisible As Boolean
    >   Set(value As Boolean)
    >     _ExcelVisible = value
    >     If Not _xlsApplication Is Nothing Then _xlsApplication.Visible = _ExcelVisible
    >   End Set
    >   Get
    >     Return _ExcelVisible
    >   End Get
    > End Property

    フラグ管理したいのであれば _xlsApplication などの COM オブジェクトを公開してはいけません。
    ExEx1.xlsApplication.Visible を直接操作されたら、上記の _ExcelVisible フラグが連動しなくなりますよね?

    同様に、Range や Worksheet や Workbook などを公開するのも問題があります。
    公開したいのであれば、カプセル化した独自のマネージ クラスを Return するようにします。


    逆に、COM オブジェクトを公開する仕様とするのであれば、ExcelEx 側の役目はヘルパーライブラリに徹するものとし、
    COM オブジェクトの解放タイミングは呼び出し側に担当させる仕様の方が良いでしょう。この場合、下記の 2 つをルールとします。

    (1) プロシージャ内で生成された COM オブジェクトは、ExcelEx 自身が即座に解放する。
    (2) 呼び出し元から渡された COM オブジェクトや、呼び出し元に Return する COM オブジェクトは、呼び出し側で解放する。
違反を報告
引用返信
■35255 / ResNo.10)  Re[6]: Excel Com オブジェクトの増殖
□投稿者/ 魔界の仮面弁士 大御所(1494回)-(2022/11/28(Mon) 06:16:23)
  • アイコンNo35251に返信(たこさんの記事)
    > 問題は無い様に思えるのですが…
    Friend Sub WorkSheet_Select には、もう一つ問題点がありそうです。

    > If Not check Then
    >   _xlsWorkSheet = CType(xlsSheets.Add(), Excel.Worksheet)
    >   xlsWorkSheet.Name = strSheetName
    > Else
    >   _xlsWorkSheet = CType(xlsSheets(strSheetName), Excel.Worksheet)
    > End If
    これだと、「以前に _xlsWorkSheet が参照していた COM オブジェクト」が
    解放されなくなってしまいます。


    No35247 において、解説の最後に
    >> Dim y As Excel.Workbooks = x.Workbooks
    >> Dim z As Excel.Workbooks = x.Workbooks
    という実験コードを書いていますが、この場合、VBA や VBS とは異なり、
    .NET においては y と z が別インスタンスとなることに注意が必要です。

    この場合、COM の参照カウントは y と z それぞれに対して減じねばなりません。
    y と z の両方を RelaseComObject した場合と、どちらか一方しか
    解放しなかった場合とで、Excel の残存性を確認してみてください。

    仮に同一インスタンスを返す仕様であったとしたら、
     Trace.WriteLine(Marshal.ReleaseComObject(z)) 'ア
     Trace.WriteLine(Marshal.ReleaseComObject(y)) 'イ
    において、ReleaseComObject の戻り値から得られる残存参照カウント数が
    「イ = ア - 1」の関係となるはずですが、実際には別インスタンスであるため
    「イ = ア」な戻り値で返されていると思います。
違反を報告
引用返信
■35256 / ResNo.11)  Re[6]: Excel Com オブジェクトの増殖
□投稿者/ radian 一般人(1回)-(2022/11/28(Mon) 11:57:41)
  • アイコンちなみに、OfficeのCOMの自動管理をやってくれるライブラリもあります。
    解放漏れを特定出来ない&コードが煩雑になっている場合、
    導入を検討してみるのも手かもしれません。

    https://www.nuget.org/packages/NetOfficeFw.Excel/
    https://github.com/NetOfficeFw/NetOffice
違反を報告
引用返信
■35257 / ResNo.12)  Re[7]: Excel Com オブジェクトの増殖
□投稿者/ たこ 一般人(19回)-(2022/11/28(Mon) 22:38:47)
  • アイコンNo35252に返信(魔界の仮面弁士さんの記事)
    No35253に返信(魔界の仮面弁士さんの記事)
    No35255に返信(魔界の仮面弁士さんの記事)
    No35256に返信(radianさんの記事)

    魔界の仮面弁士様、radian様、返信ありがとうございます。

    返信が前後しますが、まずはradian様ご紹介ありがとうございます。
    どうしようも無くなった時は検討させて頂きます(^^ゞ

    余談にはなりますが…
    元々私、プログラミングは全部独学でして、スキルアップの為に今回の質問をさせて頂いています(^^ゞ
    (いつもはどうしようも無くなって質問させて頂いていますが…(^^ゞ)
    まだしっかりと解ってる訳では無いですが、VB6.0からオブジェクトの概念を解る様になるまでは苦労しました^^;

    最終的には会社で5年分くらいExcelで見積書が溜まっていますので、これをデータベース化するのが目的です。。。
    最初はExcel VBAで5年分の見積書の内容をまとめようかと思っていましたが、クラスの概念を覚えてしまうとクラスを使った方が楽なので(^^ゞ
    VB6.0やVBAにもクラスはありますが、使い方が良く解りません…
    …と言う訳でVB.NETで…(^^ゞ

    お気持ちは有難く頂戴致しました。
    ありがとうございます。



    今回、いろいろ調べてやっとExcelのオブジェクトモデルを発見出来ました。
    https://learn.microsoft.com/ja-jp/office/vba/api/overview/excel/object-model
    VBAと同じなのですね…
    当たり前と言えば当たり前ですが…

    Option Strict Onも調べました…
    https://atmarkit.itmedia.co.jp/fdotnet/vb6tonet/vb6tonet26/vb6tonet26_03.html

    DirectCast、CTypeの違いも調べました…
    http://vb.navi-ch.net/2015/07/18/post-118/
    https://learn.microsoft.com/ja-jp/dotnet/visual-basic/language-reference/operators/directcast-operator



    さて、本題に戻ります。

    No35252に返信(魔界の仮面弁士さんの記事)
    >>  Private _xlsApplication As Excel.Application = Nothing
    >>  Friend ReadOnly Property xlsApplication As Excel.Application
    >>    Get
    >>      Return _xlsApplication
    >>    End Get
    >>  End Property
    > これではあまり意味が無いと思いますよ。結局のところ、
    >  Friend ReadOnly xlsApplication As Excel.Application
    > な読み取り専用フィールドと、さほど変わらないように見えます。
    >
    >
    > COM オブジェクトを直接公開してしまうと、ExcelEx の外部で
    >  ExEx1.xlsApplication.Workbooks.Add()
    > などと書かれてしまえば、COM オブジェクトの解放漏れに繋がります。
    >
    > IDisposable としてカプセル化するのであれば、Excel の COM オブジェクトは
    > 外部からは直接操作できないようにして、すべてクラス内に隠蔽します。
    > 戻り値と返すのも COM オブジェクトではなく、.NET のマネージオブジェクトにします。

    全てをクラス内でやってしまう…と言う考え方で良いのでしょうか…
    例えば…
    -----------------------------------------------------------------
    Private _xlsApplication as Excel.Application = Nothing

    Private _ExcelVisible As Boolean = True
    Public Property ExcelVisible As Boolean
      Set(Value as Boolean)
        _ExcelVisible = Value
        If value then
          _xlsApplication.Visible = True
        Else
          _xlsApplication.Visible = False
        End If
      End Set
      Get
        Return _ExcelVisible
      End Get
    End Property
    -----------------------------------------------------------------
    …の様な感じで…

    >>  _xlsWorkSheet = xlsApplication.Sheets.Add()
    > この処理には、問題点が 2 つあります。
    >
    > 1 つは「.」による COM オブジェクトの連続呼び出しであり、
    > Sheets プロパティから返されるコレクションの解放が漏れています。
    Excel.Applicationオブジェクト(COMモデル)の中の、Application.Sheetsプロパティ…あれ?w
    https://learn.microsoft.com/ja-jp/office/vba/api/excel.application.sheets
    COMオブジェクトの場合は(COMオブジェクトの)プロパティの解放も必要と理解して良いのでしょうか…

    >  Dim obj1 = 対象ワークブック.Sheets 'これは Sheets 型        …と言う事は Dim obj1 As Excel.Sheets
    >  Dim obj2 = obj1(strSheetName) 'これは Object 型となることに注意   …と言う事は Dim obj2 As Object
    …で合ってますかね^^?
    ここの理解はまだ追い付いていません(>_<)

    > ただし厳密にいえば、xlsSheets によって列挙されるシートが Excel.Worksheet である保証はありません。
    > Excel.Chart や Excel.DialogSheet が列挙される可能性もあることは頭の片隅に置いといてください。

    …と言う事は…
    -------------------------------------------------------------------------------------
    Friend Sub WorkSheet_Select(strSheetName As String)
      Dim check As Boolean = False
      For x As Integer = 1 to _xlsSheets.Count
        If _xlsSheets(x) Is Excel.Worksheet then                '← 怒られました^^;
          If CType(_xlsSheets (x), Excel.Worksheet).Name = strSheetName Then
            check = True
            Exit For
          End If
        End If
      Next
      If Not check Then
        _xlsWorkSheet = CType(_xlsSheets.Add(), Excel.Worksheet)
        _xlsWorkSheet.Name = strSheetName
      Else
        _xlsWorkSheet = CType(_xlsSheets(strSheetName), Excel.Worksheet)
      End If
      If SheetVisible Then _xlsWorkSheet.Select()
    End Sub
    -------------------------------------------------------------------------------------

    下の方に書いてありました^^;
    >   Dim ws = DirectCast(xlsSheets(n), Excel.Worksheet)
    これだと『WorkSheet』以外はNothingになるのでしょうか…

    (DirectCastは明示的な型変換と書いてありました…
    http://vb.navi-ch.net/2015/07/18/post-118/
    -------------------------------------------------------------------------------------
    サンプルソース
    Dim a As Object = 3.14
    Dim b As Integer = DirectCast(a, Integer)
    MsgBox(b)
    End Sub
    End Class
    実行結果
    メッセージーボックスも表示されません。
    -------------------------------------------------------------------------------------

    頭大パニック中…
違反を報告
引用返信
■35258 / ResNo.13)  Re[8]: Excel Com オブジェクトの増殖
□投稿者/ たこ 一般人(20回)-(2022/11/28(Mon) 23:06:02)
  • アイコンNo35257に返信(たこさんの記事)

    ちょっとした実験をしてみました。
    --------------------------------------------------------------------
    Dim w As Excel.Worksheets
    Dim s = w.Item(1)     '←WorkSheetオブジェクトのItemなので、当然WorkSheet型だと思っている
    Dim n = CType(s, Excel.Worksheets).name    '←怒られる…
    --------------------------------------------------------------------

    Dim s As Excel.Worksheets = w.Item(1)   '←やっぱり怒られる…
                         'Option Strict On では'Object'から'Worksheets'への暗黙的な変換は許可されていません。
                         'ReadOnly Property Excel.Wroksheets.Item(Index As Object) As Object

    Dim s As Object = w.Item(1)        'これが正解の様だ…
                         'ここは戻り値がObjectなので理解出来る。

    Dim n = CType(s, Object).name       '←怒られる…
                         'Option Strict On では、遅延バインディングを使用できません。
    一体何の型にキャストすればシート名が取得できるのだろう…

    >『.』の連続」が見えにくくなる
    .を分解するのも苦労します(>_<)

    あ…そう言えばと思い。。。

    Dim w As Excel.Worksheets
    Dim s As Object = w.Item(1)
    Dim sh As Excel.Worksheet = CType(s, Excel.Worksheet)
    Dim n As String = sh.Name

    怒られなくなりました!

    この場合、MRComObjectをしなければならないのは…
    w、s、shで合っていますでしょうか^^?


違反を報告
引用返信

■記事リスト / レス記事表示 → [親記事-9] [10-13]



■記事リスト / ▲上のスレッド
■35236 / 親記事)  二次元マップから値の取得
□投稿者/ LLCOOLJ 一般人(1回)-(2022/11/16(Wed) 14:40:05)
  • アイコン環境/言語:[vb.net] 
    分類:[.NET] 

    x,y軸からなる2次元マップから値を読み込む関数を作成し、クラス化して

    プログラムの中で利用したいと考えてます。

    どのようなコードを記述すれば良いでしょうか?

    良いサンプルコードがあればご紹介お願いします
違反を報告
引用返信

▽[全レス1件(ResNo.1-1 表示)]
■35240 / ResNo.1)  Re[1]: 二次元マップから値の取得
□投稿者/ Azulean 大御所(535回)-(2022/11/16(Wed) 21:07:48)
  • アイコンNo35236に返信(LLCOOLJさんの記事)
    > x,y軸からなる2次元マップから値を読み込む関数を作成し、クラス化して
    > プログラムの中で利用したいと考えてます。
    > どのようなコードを記述すれば良いでしょうか?

    それだけであれば、クラスを書かなくても、二次元配列にすれば良いのでは…?となってしまいます。
    まずは、「VB.NET 2次元配列」で探して学んでみてください。


    これでは足りないと考えられる場合、要件を自分の中でもっと具体的に、箇条書きなどに整理するところから始めてください。


    ' ついでに「書き込みのルールについて」も改めてご確認ください。
    https://dobon.net/vb/bbs/index.html#irresponsible
違反を報告
引用返信

■記事リスト / レス記事表示 → [親記事-1]






Mode/  Pass/


- Child Tree -