从 Excel 读取 - 以不同的列顺序写入 CSV

Read from Excel - write to CSV in different column order

我需要了解是否有可能在 VB.NET 内读取 Excel 文件的列并以不同的顺序将它们写入 CSV 文件。

实际中,我们发送的Excel文件有6栏:“金额”、“分公司”、“库存”、“方案”、“数量”、“类型”。公司管理系统接受具有不同顺序列的文本文件:“分支”、“库存”、“金额”、“数量”、“类型”、“建议”。这对我来说是个问题,因为当我去转换它时,我的 ERP无法识别该列位于不同的位置。

我到达了具体问题,我希望有可能阅读这些列并通过脚本使它们能够根据我决定的位置来定位它们。

我尝试使用此代码导入并转换为 txt,但我需要另一个脚本:

Imports System.IO
Imports ExcelDataReader
Imports System.Text

Public Class Form1

Dim tables As DataTableCollection



Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

    Using ofd As OpenFileDialog = New OpenFileDialog() With {.Filter = "(*.xls)|*.xls|(*.xls)|*.xlsx"}
        If ofd.ShowDialog() = DialogResult.OK Then
            txtFileName.Text = ofd.FileName
            Using Stream = File.Open(ofd.FileName, FileMode.Open, FileAccess.Read)
                Using reader As IExcelDataReader = ExcelReaderFactory.CreateReader(Stream)
                    Dim result As DataSet = reader.AsDataSet(New ExcelDataSetConfiguration() With {
                                                             .ConfigureDataTable = Function(__) New ExcelDataTableConfiguration() With {
                                                             .UseHeaderRow = True}})
                    tables = result.Tables
                    cboSheet.Items.Clear()
                    For Each table As DataTable In tables
                        cboSheet.Items.Add(table.TableName)
                    Next
                End Using
            End Using
        End If
    End Using

End Sub

Private Sub cboSheet_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cboSheet.SelectedIndexChanged

    Dim dt As DataTable = tables(cboSheet.SelectedItem.ToString())
    dgProposte.DataSource = dt

End Sub


Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click

    Dim writer As TextWriter = New StreamWriter("C:\Users\antonio\Desktop\Prova.txt")

    For i As Integer = 0 To dgProposte.Rows.Count - 2 Step +1
        For j As Integer = 0 To dgProposte.Columns.Count - 1 Step +1
            writer.Write(vbTab & dgProposte.Rows(i).Cells(j).Value.ToString() & vbTab & "")
        Next

        writer.WriteLine("")

    Next
    writer.Close()
    MessageBox.Show("Dati Esportati")

End Sub

为什么不映射数据的 DTO table?

Public Class MioDto
    Property campoUno As String
    Property campoDue As String
    '...ecc
End Class

然后你可以在一个cicle中填充一个dto...

Dim a As New MioDto() With {.campoUno="...", campoDue="..."}

或者如果您愿意,可以使用

https://github.com/AutoMapper/AutoMapper

填写 Dto class 后,您可以使用它生成包含您或首选订单的 txt。

您通过导入 Excel sheet(s) 得到的表设置了它们的列名,您可以按列名索引该列。

所以,稍微调整一下,找出一些方法:

Imports System.IO
Imports ExcelDataReader

Public Class Form1

    Dim tables As DataTableCollection

    Private Sub WriteToCsv(tableName As String, filename As String)
        Dim columnWriteOrder = {"branch", "stock", "amount", "quantity", "type", "proposal"}

        Using writer As TextWriter = New StreamWriter(filename)

            Dim tbl = tables(tableName)

            For i As Integer = 0 To dgProposte.Rows.Count - 2

                Dim vals As New List(Of String)

                For j As Integer = 0 To columnWriteOrder.Length - 1
                    Dim val = tbl.Rows(i).Item(columnWriteOrder(j)).ToString()
                    vals.Add(val)
                Next

                writer.WriteLine(String.Join(vbTab, vals))

            Next

        End Using

    End Sub

    Private Sub PopulateSheetNames()
        cboSheet.Items.Clear()

        For Each table As DataTable In tables
            cboSheet.Items.Add(table.TableName)
        Next

    End Sub

    Private Sub cboSheet_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cboSheet.SelectedIndexChanged
        If cboSheet.SelectedIndex >= 0 Then
            Dim tableName = cboSheet.SelectedItem.ToString()
            Dim dt As DataTable = tables(tableName)
            dgProposte.DataSource = dt
        End If

    End Sub

    Private Sub bnLoad_Click(sender As Object, e As EventArgs) Handles bnLoad.Click

        Using ofd As OpenFileDialog = New OpenFileDialog() With {.Filter = "(*.xlsx)|*.xlsx|(*.xls)|*.xls", .InitialDirectory = "C:\temp"}
            If ofd.ShowDialog() <> DialogResult.OK Then
                Exit Sub
            End If

            txtFileName.Text = ofd.FileName

            Using Stream = File.Open(ofd.FileName, FileMode.Open, FileAccess.Read)
                Using reader As IExcelDataReader = ExcelReaderFactory.CreateReader(Stream)

                    Dim edsc = New ExcelDataSetConfiguration() With {
                                                             .ConfigureDataTable = Function(__) New ExcelDataTableConfiguration() With {
                                                             .UseHeaderRow = True}}
                    Dim result As DataSet = reader.AsDataSet(edsc)

                    tables = result.Tables

                End Using
            End Using

            PopulateSheetNames()

        End Using

    End Sub

    Private Sub bnSaveAsCsv_Click(sender As Object, e As EventArgs) Handles bnSaveAsCsv.Click

        If cboSheet.SelectedIndex < 0 Then
            MessageBox.Show("Please select a sheet name.", "No sheet name selected", MessageBoxButtons.OK, MessageBoxIcon.Information)
            Exit Sub
        End If

        Dim sheetName = cboSheet.SelectedItem.ToString()

        If Not String.IsNullOrEmpty(sheetName) Then
            WriteToCsv(sheetName, "C:\temp\Prova.csv")
            MessageBox.Show("Dati Esportati.", "Dati Esportati", MessageBoxButtons.OK, MessageBoxIcon.Information)
        End If

    End Sub

End Class

我更改了按钮的名称,因为“Button1”和“Button2”没有描述性。

(我设置了OpenFileDialog的.InitialDirectory是因为方便我。)