【问题标题】:VB.net Dataset to XML Purchase OrderVB.net 数据集到 XML 采购订单
【发布时间】:2016-05-06 18:22:03
【问题描述】:

我在 VB.net 中编写了一个程序,它允许我使用 OleDB 字符串将 Excel 文件转换为 XML,将其读入 Datatable,然后读入 Dataset,最后将 Dataset 转换为 XML,这可以是保存到另一个文件中。

现在我很困惑如何让 XML 以特定方式保存元素,基本上看起来像采购订单?

我的所有当前代码和我的 excel 文件的屏幕截图如下。任何帮助表示赞赏。

如果我的代码工作正常,XML 文件应该如何查看:

 <?xml version="1.0" encoding="ASCII" standalone="yes"?>
    <CustomerPurchaseOrder xmlns="http://www.dummysite.com/">
      <CustomerPurchaseOrderFile>
      <FirstName>John</FirstName>
      <LastName>Smith</LastName>
      <OrderDate>2015-12-11</OrderDate>
      <SpecialInstructions>Leave at front door</SpecialInstructions>
      <LineItems>
        <LineItem>
          <ItemDescription>Brown Shirt</ItemDescription>
          <QTY>1</QTY>
          <Price>$12.99</Price>
        </LineItem>
        <LineItem>
          <ItemDescription>Black Shoes Pair</ItemDescription>
          <QTY>1</QTY>
          <Price>$45.89</Price>
        </LineItem>
        <LineItem>
          <ItemDescription>Oranges</ItemDescription>
          <QTY>5</QTY>
          <Price>$8.99</Price>
        </LineItem>
      </LineItems>
      <FirstName>Lisa</FirstName>
      <LastName>Lane</LastName>
      <OrderDate>2016-01-12</OrderDate>
      <SpecialInstructions />
      <LineItems>
        <LineItem>
          <ItemDescription>Wheat Bread Loaf</ItemDescription>
          <QTY>3</QTY>
          <Price>$5.99</Price>
        </LineItem>
        <LineItem>
          <ItemDescription>TV Samsung 40"</ItemDescription>
          <QTY>1</QTY>
          <Price> $539.99</Price>
        </LineItem>
      </LineItems>
      </CustomerPurchaseOrderFile>
    </CustomerPurchaseOrder>

我目前得到的 - 不是我想要的:

<?xml version="1.0" standalone="yes"?>
<CustomerPurchaseOrder xmlns="http://www.dummysite.com">
  <CustomerPurchaseOrderFile>
    <FirstName>John</FirstName>
    <LastName>Smith</LastName>
    <OrderDate>2015-12-11T00:00:00-08:00</OrderDate>
    <SpecialInstructions>Leave at front door</SpecialInstructions>
    <ItemDescription>Brown Shirt</ItemDescription>
    <QTY>1</QTY>
    <Price>12.99</Price>
  </CustomerPurchaseOrderFile>
  <CustomerPurchaseOrderFile>
    <ItemDescription>Black Shoes Pair</ItemDescription>
    <QTY>1</QTY>
    <Price>45.89</Price>
  </CustomerPurchaseOrderFile>
  <CustomerPurchaseOrderFile>
    <ItemDescription>Oranges</ItemDescription>
    <QTY>5</QTY>
    <Price>8.99</Price>
  </CustomerPurchaseOrderFile>
  <CustomerPurchaseOrderFile>
    <FirstName>Lisa</FirstName>
    <LastName>Lane</LastName>
    <OrderDate>2016-01-12T00:00:00-08:00</OrderDate>
    <ItemDescription>Wheat Bread Loaf</ItemDescription>
    <QTY>3</QTY>
    <Price>5.99</Price>
  </CustomerPurchaseOrderFile>
  <CustomerPurchaseOrderFile>
    <ItemDescription>TV Samsung 40"</ItemDescription>
    <QTY>1</QTY>
    <Price>539.99</Price>
  </CustomerPurchaseOrderFile>
</CustomerPurchaseOrder>

我的 VB.Net 代码

Imports System.Data.OleDb

Public Class Form1

    Dim myDS As DataSet
    Dim myDT As DataTable = New DataTable("CustomerPurchaseOrderFile")
    Dim myFilePath As String()

    'Load Excel File Button
    Private Sub loadFileBtn_Click(sender As Object, e As EventArgs) Handles loadFileBtn.Click
        'choose excel file
        'file dialog box properties
        OpenFileDialog1.Filter = "Excel Files (*.xls, *.xlsx)|*.xls;*.xlsx"
        OpenFileDialog1.FilterIndex = 2
        OpenFileDialog1.InitialDirectory = "C:\"
        saveXMLBtn.Enabled = False
        Dim checkOpenDialog As DialogResult = OpenFileDialog1.ShowDialog()
        Dim myConnection As String, excelConn As OleDbConnection
        Dim myAdapter As OleDbDataAdapter
        'import file using OleDB connections into datatable -> dataset -> xml
        Try
            'disable save button if no file is loaded
            If checkOpenDialog = DialogResult.Cancel Then
                saveXMLBtn.Enabled = False
            ElseIf checkOpenDialog = DialogResult.None Then
                saveXMLBtn.Enabled = False
            ElseIf checkOpenDialog = DialogResult.OK Then
                myFilePath = OpenFileDialog1.FileNames
                myConnection = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + myFilePath(0) + ";Extended Properties=""Excel 12.0;HDR=Yes;IMEX=1;"""
                excelConn = New OleDbConnection(myConnection)
                excelConn.Open()
                myAdapter = New OleDbDataAdapter("select * from [Sheet1$]", excelConn)
                myDT = New DataTable()
                myDS = New DataSet()
                myDS.Tables.Add(myDT)
                myDS.Merge(myDT)
                myDS.DataSetName = "CustomerPurchaseOrder"
                myDS.Namespace = "http://www.dummysite.com"
                myDS.Prefix = ""
                myAdapter.Fill(myDS, "CustomerPurchaseOrderFile")
                myDS.AcceptChanges()
                excelConn.Close()
                'dataset -> string storage
                Dim storeXML As String = myDS.GetXml
                'preview in text box
                xmlPreviewBox.Text = storeXML
            End If
            'save dataset to string
        Catch ex As Exception
            MsgBox(ex.ToString)
        Finally
            If myFilePath IsNot Nothing Then
                MsgBox("Preview of XML File Loaded.")
                saveXMLBtn.Enabled = True
            End If

        End Try
    End Sub
    'Save Converted Excel to XML File
    Private Sub saveXMLBtn_Click(sender As Object, e As EventArgs) Handles saveXMLBtn.Click
        'file dialog box properties
        SaveFileDialog1.Filter = "XML Files (*.xml)|*.xml"
        SaveFileDialog1.FilterIndex = 1
        SaveFileDialog1.InitialDirectory = "C:\"
        saveXMLBtn.Enabled = False
        SaveFileDialog1.ShowDialog()
        myFilePath = SaveFileDialog1.FileNames
        Try
            If SaveFileDialog1.FileName <> "" Then
                'myDS.WriteXml(myFilePath, XmlWriteMode.IgnoreSchema)
                myDS.WriteXml(myFilePath(0)) 'works and above works the same
            End If
        Catch ex As Exception
            MsgBox(ex.ToString)
        Finally
            MsgBox("XML File Saved Successfully.")
        End Try

    End Sub
End Class

My Excel File Screenshot

【问题讨论】:

  • XML 到 DataSet 并返回是丑陋的,特别是如果你有相关的表。我认为简单地从 Excel 中提取数据,然后插入表中并生成 XML 文件会更容易。乍一看生成的 XML 文件,您有多个表,就像我说的那样,根据我的经验,这会使 XML 变得一团糟。
  • 那么,您是说要省略数据集?所以基本上是 excel -> datatable -> xml .. 我可以做到,但我仍然会停留在如何将 XML 转换为我需要的正确采购订单格式的步骤上。我在这方面没有太多经验,所以我愿意接受建议和不那么笨重的代码。
  • 除非您将数据保存到数据库中,否则您应该可以完全跳过DataSet/DataTable - 只需读取 Excel 文件并将其转换为所需的 XML。你能发布一个 Excel 格式的样本吗?
  • 谢谢蒂姆,这听起来确实容易多了。我不确定如何包含我的 excel 文件,所以我在题为“我的 Excel 文件”的问题的最后添加了一个 imgur 截图截图。

标签: xml vb.net excel


【解决方案1】:

我必须弄清楚如何使用 Xdocument 和 Xelement 来使 dbasnett 的解决方案发挥作用,并进行一些其他调整以使 xml 格式符合我需要的正确格式,所以这是我的最终解决方案。谢谢大家的回复。

Dim xQuery As IEnumerable(Of XElement) = From i In xEleDoc.Elements() Select i
        For Each i As XElement In xQuery.Elements("FirstName") 'simulate customer PO
           Dim aPO As New XElement(customerInfo) 'create a PO and fill in the values
            aPO.<FirstName>.Value = xQuery.Elements("FirstName").Value
            aPO.<LastName>.Value = xQuery.Elements("LastName").Value
            aPO.<OrderDate>.Value = Date.Parse(xQuery.Elements("OrderDate").Value).ToString("yyyy-MM-dd")
            aPO.<SpecialInstructions>.Value = xQuery.Elements("SpecialInstructions").Value
            For Each line In xQuery 'create line items and fill in the values
                Dim item As New XElement(itemsOrdered)
                item.<ItemDescription>.Value = line.Elements("ItemDescription").Value
                item.<QTY>.Value = line.Elements("QTY").Value
                item.<Price>.Value = line.Elements().Last.Value
                aPO.<LineItems>.LastOrDefault.Add(item) 'add item to PO
            Next
            orderfile.Add(aPO) 'add created POs to orderfile
        Next

【讨论】:

    【解决方案2】:

    您几乎可以通过创建子 DataTable 并使用嵌套 DataRelation 链接它们来使用 Dataset 执行此操作(有关嵌套 DataRelations 的详细信息,请参阅https://msdn.microsoft.com/en-us/library/7sfkwf9s%28v=vs.110%29.aspx)。但是,您必须处理“平面”Excel 数据以适应新结构,并且您需要一个主键来将子表链接到父表(这可能会影响 XML 输出)。

    最好使用数据集加载 Excel 工作表进行处理,然后以编程方式生成 XML(请参阅https://msdn.microsoft.com/en-us/library/bb387068%28v=vs.110%29.aspx)。

    【讨论】:

      【解决方案3】:

      看起来有三个不同的部分。第一个是一组PO,所以这样定义

          Dim protoPurchaseOrders As XElement = <PurchaseOrders>
                                                </PurchaseOrders>
      

      下一部分是采购订单

          Dim protoPO As XElement = <PO>
                                        <firstname></firstname>
                                        <lastame></lastame>
                                        <orderdate></orderdate>
                                        <specialinstructions></specialinstructions>
                                        <items></items>
                                    </PO>
      

      最后,您有了将添加到采购订单中的项目的行项目。

          Dim protoitem As XElement = <item>
                                          <description></description>
                                          <QTY></QTY>
                                          <price></price>
                                      </item>
      

      这些原型可以用来创造你想要的东西。下面是一些代码,它模拟了一组带有一些行项目的两个 PO。 请注意,原型仅用于创建新的 xelements

          Dim orderfile As New XElement(protoPurchaseOrders)
          For x As Integer = 1 To 2 'simulate two customer PO's
              Dim aPO As New XElement(protoPO) 'create a PO and fill in the blanks
              aPO.<firstname>.Value = x.ToString
              aPO.<lastame>.Value = x.ToString
              aPO.<orderdate>.Value = DateTime.Now.AddDays(x).ToShortDateString
              aPO.<specialinstructions>.Value = "SI " & x.ToString
              For i As Integer = x To 3 'create line items and fill in the blanks
                  Dim item As New XElement(protoitem)
                  item.<description>.Value = "desc " & i.ToString
                  item.<QTY>.Value = i.ToString
                  item.<price>.Value = i.ToString("c2")
                  aPO.<items>.LastOrDefault.Add(item) 'add item to PO
              Next
              orderfile.Add(aPO) 'add PO to orders
          Next
          'orderfile.Save("path goes here")
      

      这增加了一层抽象 (PO),它不在“你想要的”中,但我认为它是必要的。

      上面的输出是

      <PurchaseOrders>
        <PO>
          <firstname>1</firstname>
          <lastame>1</lastame>
          <orderdate>1/30/2016</orderdate>
          <specialinstructions>SI 1</specialinstructions>
          <items>
            <item>
              <description>desc 1</description>
              <QTY>1</QTY>
              <price>$1.00</price>
            </item>
            <item>
              <description>desc 2</description>
              <QTY>2</QTY>
              <price>$2.00</price>
            </item>
            <item>
              <description>desc 3</description>
              <QTY>3</QTY>
              <price>$3.00</price>
            </item>
          </items>
        </PO>
        <PO>
          <firstname>2</firstname>
          <lastame>2</lastame>
          <orderdate>1/31/2016</orderdate>
          <specialinstructions>SI 2</specialinstructions>
          <items>
            <item>
              <description>desc 2</description>
              <QTY>2</QTY>
              <price>$2.00</price>
            </item>
            <item>
              <description>desc 3</description>
              <QTY>3</QTY>
              <price>$3.00</price>
            </item>
          </items>
        </PO>
      </PurchaseOrders>
      

      【讨论】:

      • 我从未使用过 Xelement .. 这在 openfiledialog 中有效吗?我找到了这个链接:MSDN: How to Load XML from file 该链接是否与如何完成此相关?
      • 这至少帮助我找到了正确的方向。我将发布我的最终解决方案。
      猜你喜欢
      • 2020-11-24
      • 2017-05-31
      • 2012-09-28
      • 1970-01-01
      • 2020-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多