从格式化Excel选项卡创建特定CSV输出

时间:2016-04-29 16:54:40

标签: excel excel-vba csv vba

我有一个电子表格,其标签格式如下:

|Item Number|Description|Unit of Measure|4/29/2016|4/30/2016|5/1/2016|etc..
|-----------|-----------|---------------|---------|---------|--------|
|          1|item #1    |units          |         |       10|        |
|          2|item #2    |units          |         |         |     540|
|          3|item #3    |units          |       45|       28|        |
|          4|item #4    |units          |      133|         |        |

我需要以这种格式从这个文件创建一个.CSV文件:

1,10,30042016
2,540,01052016
3,45,29042016
3,28,30042016
4,133,29042016

excel表格可以包含未来几年的日期列。输出采用A列(项目编号)并创建与具有值的天数一样多的行,它还将日期(从列)与这些值相关联。输出格式为:

料号,数量,日期(DDMMYYYY格式)

非常感谢有关创建CSV输出的任何帮助。

1 个答案:

答案 0 :(得分:0)

我认为你需要VBA才能将列转换为行。数据透视表不会创建所需的格式,但实际上可能会使用公式过度转换。

另一方面,VBA方法可以为您提供一个干净的解决方案。

以下是必要的:

  1. 遍历每一行。
  2. 在每一行中,循环显示日期列中的所有单元格。
  3. 对于以这种方式找到的每个非空单元格,创建一个输出行,其第一列的值与当前单元格的值和列标题连接,转换为所需的日期表示。
  4. 将每个输出行写入文件。
  5. 此示例代码显示了一种可能的实现。您必须将其粘贴到VBA编辑器中的标准代码模块中,并添加对 Microsoft Scripting Runtime 库的引用(通过Tools - > References添加它)。
    假设问题中的6列布局从单元格A1开始,您可以通过在立即窗口中输入ExportToCSV ActiveSheet.Range("A1:F5"), 1, 4, "D:\output.csv"来调用代码(使用CTRL + G打开)。根据需要调整参数。

    ' exports the range rngTab to the file strFilename.
    ' lngColumnID defines the column in rngTab that contains the ID for each output line.
    ' lngColumnFirstDate defines the first date column in rngTab, assuming that all following columns are date columns as well.
    Public Sub ExportToCSV(ByRef rngTab As Range, ByVal lngColumnID As Long, ByVal lngColumnFirstDate As Long, ByVal strFilename As String)
        Dim fso As Scripting.FileSystemObject
        Dim ts As Scripting.TextStream
        Dim rngHeader As Range
        Dim rngRow As Range
        Dim rngCell As Range
        Dim lngCurrentColumnInTab As Long
    
        ' open the output file
        Set fso = New FileSystemObject
        Set ts = fso.CreateTextFile(strFilename, False) ' toggle the second parameter to overwrite an existing file without warning
    
        ' define the first row as the header row
        Set rngHeader = rngTab.Rows(1)
    
        ' loop over all data rows beginning with the second one, assuming the first contains the header
        For Each rngRow In rngTab.Resize(rngTab.Rows.Count - 1).Offset(1).Rows
    
            ' loop over all cells in the current row beginning in column lngColumnFirstDate.
            ' lngCurrentColumnInTab is a counter that keeps track of the current column so that the appropriate header value can be retrieved.
            lngCurrentColumnInTab = lngColumnFirstDate
            For Each rngCell In rngRow.Resize(, rngRow.Columns.Count - lngColumnFirstDate + 1).Offset(, lngColumnFirstDate - 1).Columns
    
                ' if a non-empty cell was found, create the output line by concatenating (comma separated) the following:
                '   * the ID contained in the cell in column lngColumnID
                '   * the current cell's content
                '   * the date in the current cell's header row; it is first converted to a date and then formatted for the desired output
                ' the constructed output line is then written to the file opened as text stream ts.
                If rngCell <> "" Then ts.WriteLine rngRow.Cells(, lngColumnID) _
                                           & "," & rngCell _
                                           & "," & Format(ConvertToDate(rngHeader.Cells(, lngCurrentColumnInTab)), "ddmmyyyy")
                lngCurrentColumnInTab = lngCurrentColumnInTab + 1
    
            Next rngCell
    
        Next rngRow
    
        ' everything was written, close the file
        ts.Close
    End Sub
    
    
    ' helper function to convert a string in the format m/d/y to a date
    Private Function ConvertToDate(ByVal strDate As String) As Date
        ConvertToDate = DateSerial(Split(strDate, "/")(2), Split(strDate, "/")(0), Split(strDate, "/")(1))
    End Function
    

    我希望这些评论能够清楚地说明各自的代码片段是做什么的。

    如果选择不一致的参数,则此代码不是防故障的。如果需要,可以扩展代码以捕获所有无效参数星座并提供详细的错误消息。