VB.net数据集到XML采购订单

时间:2016-01-29 05:14:16

标签: xml vb.net excel

我在VB.net中编写了一个程序,它允许我使用OleDB字符串将Excel文件转换为XML,将其读入Datatable,然后读入数据集,最后将数据集转换为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

3 个答案:

答案 0 :(得分:0)

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

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

下一部分是PO

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

最后您将获得将添加到PO中的项目的订单项。

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

这些原型可用于创建您想要的东西。下面是一些代码模拟一组包含一些订单项的两个订单项的代码。 请注意,原型仅用于创建新的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>

答案 1 :(得分:0)

通过创建子DataTable并使用嵌套的DataRelation链接它们,您几乎可以使用数据集执行此操作(有关嵌套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)。

答案 2 :(得分:0)

我必须弄清楚如何使用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