如何将被拒绝的行重定向到另一个文件?

时间:2014-02-13 13:33:17

标签: csv vbscript

这是我的来源csv文件

col1,col2,col3,col4,col5,col6
1,A,AA,X,Y,H
2,B,,,CC,D, -- reject this row because (CC)it should be in col3
3,E,FF,Y,L
4,G,,,XX,P,B -- reject this row because(XX) it should be in col3
5,P,Kk,,,D,M -- this is correct record since kk 2 letter digit is in col3
6,G,MM,,,,-- correct record since record MM is in col3 

如何验证此csv文件?

这样我就可以在2 [col3]

中获得所有column 3个字母

我正在按照这些步骤将源文件复制到另一个文件中(因为我不在源文件中操作)然后

我没有得到如何将被拒绝的行放入另一个文件中,请有人帮助我!

Sub test()

    '///OPEN FILE and READ
    Set objFileToRead = CreateObject("Scripting.FileSystemObject").OpenTextFile("C:\coe.txt", 1)
    'Set objFileToWrite = CreateObject("Scripting.FileSystemObject").OpenTextFile("C:\copyme2.txt", 2)
    strFileText = objFileToRead.ReadAll()
    objFileToRead.Close


    ' ///PASTE
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    Set objFileToWrite = objFSO.OpenTextFile("c:\cou.txt", 2)
    objFileToWrite.Write strFileText
    objFileToWrite.Close

End Sub

1 个答案:

答案 0 :(得分:3)

如果您是VBScript的新手,您应该开始编写计划(主要任务,子任务,解决每项任务的想法)和骨架.vbs,这样可以轻松地尝试使用解决方法(子)任务。

在您的情况下,主要任务是“将源文件中的坏行过滤到目标文件”。如果您可以“读取源文件的行”,“识别坏的行”,并“将它们写入目标文件”,则可以解决此任务。

读取文件行的​​默认方式是:

  Dim tsIn : Set tsIn = goFS.OpenTextFile("..\data\21755767.csv")
  Do Until tsIn.AtEndOfStream
     Dim sLine : sLine = tsIn.ReadLine()
  Loop
  tsIn.Close

“默认”表示:您必须有非常好/特定的理由才能选择此成语(例如:在短文件上使用.ReadAll()进行就地编辑或调试显示)或偏离它(例如:如果您的文件是UTF-16编码,则不能依赖.OpenTextFile的默认参数)。对于某些暴行 - 例如

  Do While Not tsIn.AtEndOfStream = "False"

没有任何借口。

将(某些)行写入另一个文件应如下所示:

  Dim tsOut : Set tsOut = goFS.CreateTextFile("..\data\21755767-bads.csv")
  Dim tsIn  : Set tsIn  = goFS.OpenTextFile("..\data\21755767.csv")
  Do Until tsIn.AtEndOfStream
     Dim sLine : sLine = tsIn.ReadLine()
     If True Then
        tsOut.WriteLine sLine
     End If
  Loop
  tsIn.Close
  tsOut.Close

使用.CreateTextFile(JustTheFileSpec)而不是.OpenTextFile(很多,其他,args)是标准情况下最简单/清晰/错误保存的方法:每次运行的新(可能是空的)目标文件脚本。

如上所述,附加

  WScript.Echo  goFS.OpenTextFile("..\data\21755767-bads.csv").ReadAll()

显示正常。

过滤器子任务的想法是基于观察结果:

  1. 标题行包含正确数量的字段/逗号
  2. 违规行包含错误数量的逗号
  3. 然后很容易将上述工作的结果合并到:

      Dim tsOut   : Set tsOut = goFS.CreateTextFile("..\data\21755767-bads.csv")
      Dim tsIn    : Set tsIn  = goFS.OpenTextFile("..\data\21755767.csv")
      Dim sLine   : sLine     = tsIn.ReadLine()
      Dim nUBSeps : nUBSeps   = UBound(Split(sLine, ","))
      Do Until tsIn.AtEndOfStream
         sLine = tsIn.ReadLine()
         If nUBSeps <> UBound(Split(sLine, ",")) Then
            tsOut.WriteLine sLine
         End If
      Loop
      tsIn.Close
      tsOut.Close
    

    完整的脚本:

    Option Explicit ' (1)
    
    Dim goFS : Set goFS = CreateObject("Scripting.FileSystemObject") ' (2)
    
    WScript.Quit demoReadFile() ' (3)
    WScript.Quit demoReadWriteFile()
    WScript.Quit demoFilterBads()
    
    Function demoReadFile() ' (4)
      demoReadFile = 0
      Dim tsIn : Set tsIn = goFS.OpenTextFile("..\data\21755767.csv")
      Do Until tsIn.AtEndOfStream
         Dim sLine : sLine = tsIn.ReadLine()
         WScript.Echo tsIn.Line - 1, sLine
      Loop
      tsIn.Close
    End Function
    
    Function demoReadWriteFile() ' (5)
      demoReadWriteFile = 0
      Dim tsOut : Set tsOut = goFS.CreateTextFile("..\data\21755767-bads.csv")
      Dim tsIn  : Set tsIn  = goFS.OpenTextFile("..\data\21755767.csv")
      Do Until tsIn.AtEndOfStream
         Dim sLine : sLine = tsIn.ReadLine()
         If True Then
            tsOut.WriteLine sLine
         End If
      Loop
      tsIn.Close
      tsOut.Close
      WScript.Echo  goFS.OpenTextFile("..\data\21755767-bads.csv").ReadAll()
    End Function
    
    Function demoFilterBads() ' (6)
      demoFilterBads = 0
      Dim tsOut   : Set tsOut = goFS.CreateTextFile("..\data\21755767-bads.csv")
      Dim tsIn    : Set tsIn  = goFS.OpenTextFile("..\data\21755767.csv")
      Dim sLine   : sLine     = tsIn.ReadLine()
      Dim nUBSeps : nUBSeps   = UBound(Split(sLine, ","))
      Do Until tsIn.AtEndOfStream
         sLine = tsIn.ReadLine()
         If nUBSeps <> UBound(Split(sLine, ",")) Then
            tsOut.WriteLine sLine
         End If
      Loop
      tsIn.Close
      tsOut.Close
      WScript.Echo  goFS.OpenTextFile("..\data\21755767-bads.csv").ReadAll()
    End Function
    

    示例输出:

    demoReadFile()

    cscript 21755767.vbs
    1 col1,col2,col3,col4,col5
    2 1,A,AA,X,Y
    3 2,B,,,CC,D
    4 3,E,FF,Y,
    5 4,G,,,XX,P
    

    demoFilterBads()

    cscript 21755767.vbs
    2,B,,,CC,D
    4,G,,,XX,P
    

    这样的脚本可以从骨架/模板开始,如:

    Option Explicit ' (1)
    
    Dim goFS : Set goFS = CreateObject("Scripting.FileSystemObject") ' (2)
    
    WScript.Quit step00() ' (3)
    WScript.Quit step01()
    
    ...
    
    Function step00() ' (4)
      step00 = 0
      ...
    End Function
    
    1. 所有脚本都应以“Option Explicit”开头,以防止拼写错误的变量名称
    2. 如果你允许全局变量,那么goFS是一个很好的候选者。如果没有,只创建一个FSO并将其传递给需要它的Subs / Functions / Methods。 从不每次需要其方法/属性时都会创建新的FSO。
    3. 使用注释或重新排序来调用当前使用的功能
    4. '样本'功能;写下很多来检查/阐述你的想法
    5. 更新评论:

      添加效用函数:

      Function qq(s) : qq = """" & s & """" : End Function
      

      和实验/探索功能:

      Function demoFilterSteps()
        demoFilterSteps = 0
        Dim sLine
        For Each sLine In Split("col1,col2,col3,col4,col5 1,A,AA,X,Y 2,B,,,CC,D")
            WScript.Echo 0, qq(sLine)
            Dim aParts  : aParts  = Split(sLine, ",")
            Dim nUBSeps : nUBSeps = UBound(aParts)
            WScript.Echo 1, nUBSeps, qq(Join(aParts, "-"))
      
            WScript.Echo
        Next
        nUBSeps = 4            ' correct
        sLine   = "2,B,,,CC,D" ' bad
        Dim sExpr : sExpr = "nUBSeps <> UBound(Split(sLine, "",""))"
        WScript.Echo 2, nUBSeps, qq(sLine), sExpr, CStr(Eval(sExpr))
      End Function
      

      输出:

      cscript 21755767.vbs
      0 "col1,col2,col3,col4,col5"
      1 4 "col1-col2-col3-col4-col5"
      
      0 "1,A,AA,X,Y"
      1 4 "1-A-AA-X-Y"
      
      0 "2,B,,,CC,D"
      1 5 "2-B---CC-D"
      
      2 4 "2,B,,,CC,D" nUBSeps <> UBound(Split(sLine, ",")) True
      

      要查看

      1. 拆分标题行会导致nUBSep为4(5个字段之间有4个分隔符)
      2. 好的一行也会导致nUBSeps为4 - 这并不奇怪
      3. 坏行给出nUBSeps不同(&lt;&gt;)4;本示例中的5
      4. 假设nUBSeps为4(正确),表达式nUBSeps <> UBound(Split(sLine, ","))的计算结果为True,当sLine保持错误的行 - 这样该行应该写入目标文件