使用VBA从Excel生成动态CSV

使用VBA从Excel生成动态CSV,excel,vba,csv,Excel,Vba,Csv,我们要求用户可以隐藏/取消隐藏Excel列并在其中移动。 一旦用户单击generate CSV按钮,我们希望列按特定顺序排列。 例如 Col1、Col2、Col3是Excel第一行A、B、C列中的列标题。 用户将列Col2移动到末尾,并隐藏了Col2: A、 B、C列现在有标题:Col1、Col3、Col2(隐藏) 我们的CSV文件应生成为:Col1、Col2、Col3。 使用下面的代码,我们无法看到Col2,即使我们设法取消隐藏,我们怎么知道用户在最后移动了Col2 Public Sub Ex

我们要求用户可以隐藏/取消隐藏Excel列并在其中移动。 一旦用户单击generate CSV按钮,我们希望列按特定顺序排列。 例如 Col1、Col2、Col3是Excel第一行A、B、C列中的列标题。 用户将列Col2移动到末尾,并隐藏了Col2: A、 B、C列现在有标题:Col1、Col3、Col2(隐藏)

我们的CSV文件应生成为:Col1、Col2、Col3。 使用下面的代码,我们无法看到Col2,即使我们设法取消隐藏,我们怎么知道用户在最后移动了Col2

Public Sub ExportWorksheetAndSaveAsCSV()

Dim csvFilePath As String
Dim fileNo As Integer
Dim fileName As String
Dim oneLine As String
Dim lastRow, lastCol As Long
Dim idxRow, idxCol As Long
Dim dt As String

dt = Format(CStr(Now), "_yyyymmdd_hhmmss")
' --- get this file name (without extension)
fileName = Left(ThisWorkbook.Name, InStrRev(ThisWorkbook.Name, ".", -1, vbTextCompare) - 1)
' --- create file name of CSV file (with full path)
csvFilePath = ThisWorkbook.Path & "\" & fileName & dt & ".csv"
' --- get last row and last column
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
lastCol = Cells(1, Columns.Count).End(xlToLeft).Column
' --- open CSC file
fileNo = FreeFile
Open csvFilePath For Output As #fileNo
' --- row loop
For idxRow = 1 To lastRow
    If idxRow = 2 Then
        GoTo ContinueForLoop
    End If
    oneLine = ""
    ' --- column loop: concatenate oneLine
    For idxCol = 1 To lastCol
        If (idxCol = 1) Then
            oneLine = Cells(idxRow, idxCol).Value
        Else
            oneLine = oneLine & "," & Cells(idxRow, idxCol).Value
        End If
    Next

    ' --- write oneLine > CSV file
    Print #fileNo, oneLine  ' -- Print: no quotation (output oneLine as it is)
ContinueForLoop:
Next
' --- close file
Close #fileNo

End Sub

如果标题名是固定的(并且只有位置不同),那么您可以在标题上循环查找所需的标题,并注意它们的位置:然后使用该信息将单元格的值写入输出文件

公共子导出工作表和SAVEASCSV()
将csvFilePath设置为字符串
Dim fileNo为整数
将文件名设置为字符串
将一行变暗为字符串
最后一排一样长
Dim idxRow,idxCol与长
Dim dt作为字符串,ws作为工作表,hdr,arrCols,arrPos,i作为长度,f作为范围,sep
设置ws=ActiveSheet'或其他任何内容
lastRow=ws.Cells(ws.Rows.Count,1).End(xlUp).Row
'查找所有必需的列
arrCols=数组(“Col1”、“Col2”、“Col3”)
ReDim arrPos(LBound(arrCols)至UBound(arrCols))
对于i=LBound(arrCols)到UBound(arrCols)
'注意:lookin:=xlFormulas查找隐藏单元格,但lookin:=xlValues不。。。
集合f=ws.Rows(1).Find(arrCols(i),lookat:=xlother,LookIn:=xlFormulas)
如果不是的话,那么f什么都不是
arrPos(i)=f柱
其他的
MsgBox“必需列”&arrCols(i)和“未找到!”_
vbCritical,“缺少列标题”
出口接头
如果结束
接下来我
'完成查找列
fileName=Left(ThisWorkbook.Name,InStrRev(ThisWorkbook.Name,“.”,-1,vbTextCompare)-1)
dt=格式(CStr(现在),“\u yyyymmdd\u hhmmss”)
csvFilePath=thisvoolk.Path&“\”文件名&dt&“.csv”
fileNo=FreeFile
打开csvFilePath,输出为#fileNo
对于idxRow=1到lastRow
如果idxRow 2,则
oneLine=“”
sep=“”
'在定位的列位置上循环
对于idxCol=LBound(arrPos)到UBound(arrPos)
oneLine=oneLine&sep&ws.Cells(idxRow,arrPos(idxCol)).Value
sep=“,”
下一个
打印#文件号,单行
如果结束
下一个
关闭#文件否”--关闭文件
端接头
以给定的列顺序导出到CSV
  • 假设表(第一行是标题)是连续的(没有空行或空列),并且从单元格
    A1
    开始
选项显式
次级出口总额()
Const wsName As String=“Sheet1”
常量时间模式为字符串=“\u yyyymmdd\u hhmmss”
Dim hCols作为变量:hCols=VBA.Array(“Col1”、“Col2”、“Col3”、“Col4”)
将wb设置为工作簿:设置wb=ThisWorkbook
将ws设置为工作表:设置ws=wb.Worksheets(wsName)
'如果数据不连续,您可能需要一些不同的内容。
变暗rg为范围:设置rg=ws.Range(“A1”).CurrentRegion
尺寸数据作为变量:数据=rg.值
Dim hData作为变量:hData=rg.Rows(1).值'For'Application.Match'
长度为的Dim rCount:rCount=UBound(数据,1)
Dim cHeader作为变体
Dim dHeader作为变型
Dim cIndex作为变体
变光温度
变暗r为长,c为长
对于c=0至UBound(hCols)
cHeader=hCols(c)
dHeader=数据(1,c+1)
如果是切德尔·德海德,那么
cIndex=Application.Match(cHeader,hData,0)
如果是数字(cIndex),则
对于r=1,则为rCount
温度=数据(r、c+1)
数据(r,c+1)=数据(r,cIndex)
数据(r,cIndex)=温度
下一个r
如果结束
如果结束
下一个c
将时间戳设置为字符串
时间戳=格式(CStr(现在),时间模式)
作为字符串的Dim BaseName
BaseName=Left(wb.Name,InStrRev(wb.Name,“.”)1)
将文件路径设置为字符串
FilePath=wb.Path&“\”&BaseName&TimeStamp&“.csv”
Application.ScreenUpdating=False
使用工作簿。添加
.工作表(1).范围(“A1”).调整大小(rCount,UBound(数据,2)).值=数据
.SaveAs文件名:=文件路径,文件格式:=xlCSV
“”分号用户”可能需要此选项:
'.SaveAs Filename:=FilePath,FileFormat:=xlCSV,Local:=True
.结束
以
'在工作表中测试结果:
'ws.Range(“F1”)。调整大小(rCount,UBound(数据,2))。值=数据
Application.ScreenUpdating=True
端接头

如果标题名是固定的(并且只有位置不同),那么您可以在标题上循环查找所需的标题,并记下它们的位置:然后使用该信息将单元格的值写入输出文件。我不知道我可以理解您的问题。。。那么,有三个以上的栏目吗?如果是,您是否只需要前三个订单?如果不是,为什么要计算最后一列的编号?进行这种迭代时,还将考虑隐藏列单元格值,并将其放置在输出的csv文件中。这是你需要的吗?如果是,为什么要隐藏它?如果前三列是根据它们的标题排序的,那么很明显隐藏的列就是代码隐藏的列。至少,代码可以检查它。是不是我错过了什么?你能解释我的问题吗?边注,考虑一次抓取整行,把它转换成一个一维的变体数组,然后使用<代码>字符串。加入< /COD>将数组中的值连接成一个字符串,而不需要迭代列。第一步是确定如何判断给定列是否已移动。这些栏目有标题吗