北の窓から(芦田っち)

PC関連と私的雑感のブログ。
2015年7月10日、カッコ内に名前を加えました。昔の友だちに気付いてほしくて・・・

【VB.NET】 XML ファイルのインポート・エクスポート

2017-08-10 14:17:56 | VB.NET
ここでは XML 形式のファイルの入出力を説明します。

  言語は VB.NET です。

  画面(WindowsForm)に表示するために、DataGridView を使っています。
  XML ファイルを読み込み、DataGridView に表示し、それを XML ファイルに書き出しています。

  DataGridView は先頭列でソートしできるので、書き出した結果が元と違っているのが分かります。

なお、このサンプルは MSDN フォーラムでの問い合わせ対応用に作ったものです。

  元の XML ファイル(Family.xml)を Excel で開くと次のように見えます。
  

  テキストエディターで開くと、こんな感じ・・・
  

  1列目がファーストネーム、2列目がラストネーム、3列目が電話番号です。

サンプルを実行するとこのようになります。

  1.XML ファイルをインポートし DataGridView に格納
  2.ファーストネームでソート
  3.それを XML ファイルにエクスポート

  
  
さて、画面とコードは次のとおりです。

メインフォームの画像:
  

メインフォームのコード:
-------------------------------------------------------------------
Public Class frm_Main
#Region "=== Form: Load, Closing"
  Private Sub frm_Main_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Call cls_DGV.prc_Prepare_dgv_Family()
  End Sub
#End Region

#Region "=== [Button]"
   --[Import] buttn: Read XML and store data to DGV
  Private Sub btn_OpenFile_Click(sender As Object, e As EventArgs) Handles btn_Import.Click
    With Me.OpenFileDialog1
      .InitialDirectory = System.Reflection.Assembly.GetExecutingAssembly().Location
      .Title = "Select an XML file"
      .Filter = "XML file (*.xml)|*.xml"
  End With
    If (Me.OpenFileDialog1.ShowDialog = DialogResult.OK) Then
      Me.txt_InputFileName.Text = Me.OpenFileDialog1.FileName
      Call Me.prc_Create_OutputFileName(Me.OpenFileDialog1.FileName)
      Call cls_DGV.prc_Clear_dgv_Family()
      Call cls_FileIO.prc_Read_File()
      Me.dgv_Family.ClearSelection()
    End If
  End Sub

  ' --- decide output file name: addding "_Sorted" to original name
  Private Sub prc_Create_OutputFileName(ByVal inputFileName As String)
    ' --- decide file name WithOut Path
    Dim fileNameWOPath As String = System.IO.Path.GetFileName(inputFileName)
    Dim extension As String = System.IO.Path.GetExtension(inputFileName)
    fileNameWOPath = fileNameWOPath.Replace(extension, "_Sorted.xml")
    ' --- decide file name with Path
    Dim dirName As String = System.IO.Path.GetDirectoryName(inputFileName)
    Me.txt_OutputFileName.Text = dirName & "\" & fileNameWOPath
  End Sub

  ' ---[Sort] button
  Private Sub btn_Sort_Click(sender As Object, e As EventArgs) Handles btn_Sort.Click
    ' --- sort columns(0): f_name -- ascending
    Me.dgv_Family.Sort(dgv_Family.Columns(0), System.ComponentModel.ListSortDirection.Ascending)
    Me.dgv_Family.ClearSelection()
  End Sub

  ' ---[Export] button: Write XML using DGV data
  Private Sub btn_Export_Click(sender As Object, e As EventArgs) Handles btn_Export.Click
    Call cls_FileIO.prc_Write_File()
    If (MessageBox.Show _
      ("Export completed." & Chr(13) & "Open the exported file?", "Open?", MessageBoxButtons.YesNo) _
      = DialogResult.Yes) Then
      Dim p As System.Diagnostics.Process _
        = System.Diagnostics.Process.Start(Me.txt_OutputFileName.Text)
    End If
  End Sub
#End Region
End Class
-------------------------------------------------------------------

cls_DGV のコード:
・・・メインフォーム上の DataGridView(dgv_Family)を定義する処理と
   DataGridView をクリアする処理です。
-------------------------------------------------------------------
Public Class cls_DGV
  Inherits frm_Main

  ' --- Prepare dgv_Family
  Public Sub prc_Prepare_dgv_Family()
    With frm_Main.dgv_Family
      .ColumnHeadersHeight = 30           ' -- 列見出しの高さ
      .RowTemplate.Height = 30            ' -- 行の高さ
      .RowHeadersVisible = False          ' -- ● 左端のレコードセレクターは非表示
      .MultiSelect = False                ' -- 複数選択は不可
      .AllowUserToAddRows = False         ' -- 行の追加禁止(末尾の新規行を表示しない)
      .AllowUserToResizeColumns = True    ' -- 列幅変更を許可
      .BackgroundColor = Color.WhiteSmoke ' -- 背景色
      .AlternatingRowsDefaultCellStyle.BackColor = Color.WhiteSmoke   ' -- 1行おきの色
      .SelectionMode = DataGridViewSelectionMode.FullRowSelect        ' -- 選択は行全体
      ' --- ヘッダーの背景色
      .EnableHeadersVisualStyles = False  ' -- これが必要
      .ColumnHeadersDefaultCellStyle.BackColor = Color.Gainsboro
      .RowHeadersDefaultCellStyle.BackColor = Color.Gainsboro
      ' --- 列幅(初期値として)
      .AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill
      .Columns(0).FillWeight = 30 ' -- f_name
      .Columns(1).FillWeight = 30 ' -- l_name
      .Columns(2).FillWeight = 40 ' -- tel
      ' --- 文字位置(ヘッダーはすべて中央揃え)
      For idx As Integer = 0 To .Columns.Count - 1
        .Columns(idx).HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter
      Next
    End With
  End Sub

  ' --- Clear dgv_Family: delete all rows
  Public Sub prc_Clear_dgv_Family()
    For r As Integer = 0 To frm_Main.dgv_Family.Rows.Count - 1
      frm_Main.dgv_Family.Rows.RemoveAt(0)
    Next
  End Sub
End Class
-------------------------------------------------------------------

一番大事なファイル入出力のコード:
-------------------------------------------------------------------
Imports System.Xml      ' -- XML

Public Class cls_FileIO
  Inherits frm_Main

#Region "=== Variables"
  private xmlWtr As System.Xml.XmlTextWriter
  Private Col_0, Col_1, Col_2 As String
  Private maxCol As Integer = 2   ' -- last column index to export
#End Region

#Region "=== Read XML"
  ' --- Import from XML
  Public Sub prc_Read_File()
    If (System.IO.File.Exists(frm_Main.txt_InputFileName.Text) = False) Then
      MessageBox.Show("File does not exist." & Chr(13) & frm_Main.txt_InputFileName.Text)
      Exit Sub    ' --▶ 処理を抜ける
    End If
    ' --- load XML file: XmlTextReader
    Dim xmlRdr As New XmlTextReader(frm_Main.txt_InputFileName.Text)
    Dim myRow As Integer = 0
    ' --- Read XML file
    While xmlRdr.Read()
      If (xmlRdr.NodeType = XmlNodeType.Element) Then
        ' frm_Main.dgv_Family.Rows.Add()  ' --◀ add row in DGV
        ' ---
        Select Case xmlRdr.Name
          Case = "f_name"
            frm_Main.dgv_Family.Rows.Add()  ' --◀ add Row in DGV
            frm_Main.dgv_Family(0, myRow).Value = xmlRdr.ReadString()
          Case = "l_name"
            frm_Main.dgv_Family(1, myRow).Value = xmlRdr.ReadString()
          Case = "tel"
            frm_Main.dgv_Family(2, myRow).Value = xmlRdr.ReadString()
            myRow += 1                      ' --◀ add Row index
        End Select
      End If
    End While
    ' --- post process
    xmlRdr.Close()
    xmlRdr.Dispose()
  End Sub
#End Region

#Region "=== Write XML"
  ' --- Export to XML
  Public Sub prc_Write_File()
    ' --- create instance of XML Writer
    xmlWtr = New XmlTextWriter(frm_Main.txt_OutputFileName.Text, System.Text.Encoding.UTF8)
    ' --- output XML definition
    xmlWtr.WriteStartDocument(True)
    xmlWtr.Formatting = Formatting.Indented
    xmlWtr.Indentation = 4
    xmlWtr.WriteStartElement("Hokusosha")    ' -- Space is not permitted
    ' --- dgv_Family: Loop by Rows
    Dim myRow As Integer
    For myRow = 0 To frm_Main.dgv_Family.RowCount - 1
      Call Me.prc_XML_Null_Handling(myRow) ' -- Null handling
      xmlWtr.WriteStartElement("Line")
      Call Me.sub_CreateNode _
        (Col_0, Col_1, Col_2, xmlWtr)    ' -- create node (columns 0-2)
      xmlWtr.WriteEndElement()
    Next
    ' --- post process
    xmlWtr.WriteEndElement()
    xmlWtr.WriteEndDocument()
    xmlWtr.Flush()          ' -- settle
    xmlWtr.Close()          ' -- close
    xmlWtr.Dispose()        ' -- release from memory
  End Sub

  ' --- Null handling(3 columns:0~2)
  Private Sub prc_XML_Null_Handling(ByVal R As Integer)
    If (IsDBNull(frm_Main.dgv_Family(0, R).Value)) Then
      Me.Col_0 = ""
     Else
      Me.Col_0 = frm_Main.dgv_Family(0, R).Value.ToString
    End If
    ' ---
    If (IsDBNull(frm_Main.dgv_Family(1, R).Value)) Then
      Me.Col_1 = ""
    Else
      Me.Col_1 = frm_Main.dgv_Family(1, R).Value.ToString
    End If
    ' ---
    If (IsDBNull(frm_Main.dgv_Family(2, R).Value)) Then
      Me.Col_2 = ""
    Else
      Me.Col_2 = frm_Main.dgv_Family(2, R).Value.ToString
    End If
  End Sub

  ' --- Create XML nodes (argument: column 0, 1, 2, and XmlTextWriter)
  Private Sub sub_CreateNode _
    (ByVal col_0 As String, ByVal col_1 As String, ByVal col_2 As String,
     ByVal writer As XmlTextWriter)
    ' --- XML node start: output only columns 0-2
    With frm_Main.dgv_Family
      ' -- 0: f_name
      xmlWtr.WriteStartElement(.Columns(0).Name)
      xmlWtr.WriteString(col_0)
      xmlWtr.WriteEndElement()
      ' -- 1: l_name
      xmlWtr.WriteStartElement(.Columns(1).Name)
      xmlWtr.WriteString(col_1)
      xmlWtr.WriteEndElement()
      ' -- 2: tel
      xmlWtr.WriteStartElement(.Columns(2).Name)
      xmlWtr.WriteString(col_2)
      xmlWtr.WriteEndElement()
    End With
  End Sub
#End Region
End Class
-------------------------------------------------------------------

要するに・・・XML ファイルの3列(ゼロ~2)を
  XmlTextReader で読み込み、
  XmlTextWriter で書き込む・・・そんな処理です。

  XML ファイルは実行ファイルと同じフォルダーに置いています。

最後までお読みいただき、ありがとうございます。

  このサンプルプロジェクトを OneDrive に置いています。
  お礼代わりにこれをシェアいたします。


  ソースコード付きなので適宜修正してご利用ください。
  ここをクリックすれば 99 XML_ImportExport.zip がダウンロードできます。

  # 2019-06-26 追記
    OneDrive で共有していたものを削除していたようです。
    共有要望をいただいたので、再度アップロード・共有しました。

なお、コードのキレイさ(汚さ)は笑って無視してください。

  前述のとおり、MSDN での問い合わせに対応するため
  急いで既存処理を寄せ集めただけですから・・・

また、コードをそのままブログに貼り付けるとインデントが無くなり
全ての行頭が左端に寄ってしまいました。

  なので、各行の先頭(空白部)は全角スペースで埋めています。
  ご承知おきください。

---------------------------------------------------------
ブログ記事についてのお問い合わせは「質疑応答 掲示板」で・・・

  # ご質問にはできる限りお答えしています。
    ただし、お名前(本名)を書いていただいた場合に限らせていただきます。


ここをクリックして、北窓舎のサイトにもお立ち寄りください・・・

コメント (2)    この記事についてブログを書く
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« サンマは目黒、スマホ充電は ... | トップ | おやぢチップス (78):Androi... »
最新の画像もっと見る

2 コメント

コメント日が  古い順  |   新しい順
公開しました (北窓舎のオヤヂ)
2019-06-25 16:37:21
三浦さん、お問い合わせ(ご要望)をいただき、ありがとうございました。
今、再度 OneDrive にアップロードして共有しました(ダウンロード可能にしました)。
ご確認ください。
返信する
99 XML_ImportExport.zip ファイルについて (三浦信二)
2019-06-25 15:15:44
99 XML_ImportExport.zipを再度公開して頂けないでしょうか。
返信する

コメントを投稿

ブログ作成者から承認されるまでコメントは反映されません。

VB.NET」カテゴリの最新記事