VBA:清除剪贴板并在每个循环中重新填充

VBA: Clear Clipboard and Repopulate Within Each Loop

提问人:AuldNoob 提问时间:8/11/2023 最后编辑:AuldNoob 更新时间:8/12/2023 访问量:76

问:

设置

我的源 Excel 文件有 10k 行,每行 32 列。我需要将其分解为 10 个文件,每个文件为 1k,并提取一个特定的列 AD 以供进一步处理。

列 AD 是一个文本字符串,其中包含我需要保留的特殊字符,我正在尝试从过滤的字符串中删除不需要的双引号,以便稍后粘贴到另一个应用程序中。

问题陈述

只有第一个文件正确保存。第二个文件重复第一个循环中的信息,并使用第二个循环中过滤的行对其进行更新,第三个文件包含来自第一个、第二个和第三个循环等的数据。也就是说,当我们到达第 10 个文件时,我有 10k 行而不是 1k

问题

如何在循环之间清除剪贴板,以便清空 DataArray 和剪贴板,并用该特定循环的过滤文本重新填充?

我的(经过解释编辑)VBA是:

Sub SaveFiles()

'Declarations

Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets("SourceData")
Dim Insert As Long, Max_Ins As Long, i As Long
Dim DataArr() As Variant
Dim objData As New DataObject
Dim concat As String, cellValue As String


'begin filtering Source Data Sheet to target required rows
Max_Ins = Application.WorksheetFunction.Max(ws.Range("AF:AF"))
ActiveSheet.Range("A:AF").AutoFilter Field:=27, Criteria1:="Ins"
    
For Insert = 1 To Max_Ins
           ' "Insert" is a cell on the Source Sheet which assigns rows 2 to 1000 as 1, 1001 to 2000 as 2 etc.
            ActiveSheet.Range("$AF:$AF").AutoFilter Field:=32, Criteria1:=Insert
           ' I only need to process column AD for this exercise
            Range("AD1").Select
            Range(Selection, Selection.End(xlDown)).Select
            Selection.SpecialCells(xlCellTypeVisible).Select
            Selection.Copy

' I need the data in a new workbook
    Workbooks.Add
    Range("A1").Select
    Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
        :=False, Transpose:=False
    Rows("1:1").Select
    Application.CutCopyMode = False
    Range("A1").Select
    Range(Selection, Selection.End(xlDown)).Select

'now I have my 'mini file' created I want to load the data into an array for processing.
Erase DataArr
DataArr = Selection

' I found this in another post, and it's successfully removing the double quotes from the data so I can then copy/paste it correctly later.
        For i = LBound(DataArr, 1) To UBound(DataArr, 1)
                         If IsNumeric(DataArr(i, 1)) Then
                            cellValue = LTrim(Str(DataArr(i, 1)))
                        Else
                            cellValue = DataArr(i, 1)
                        End If
                        
                        concat = concat + CR + cellValue
                        CR = Chr(13)
                        objData.SetText (Mid(concat, 3))
                        objData.PutInClipboard
        Next i
        
'Now my text is as I need it, i'm trying to paste it back into the workbook.
'I start by removing the existing data (which is now in the array, and has been cleansed)
    Range("A1").Select
    Range(Selection, Selection.End(xlDown)).Select
    Selection.ClearContents
'then paste back the objData cleansed values
    Range("A1").Select
    ActiveSheet.PasteSpecial Format:="Unicode Text", Link:=False, _
    DisplayAsIcon:=False, NoHTMLFormatting:=True
    
'I don't need the header row in my final files but it seems good to have it processed as, without it, the first line is usually 3 chara
    Range("A1").Select
    Selection.Delete Shift:=xlUp
    
'Attempting to clear the Clipboard in objdata ready for the next loop.
'This is the part which I need help with as it's not working and so the 2nd loop retains the data from the first loop and then adds the 2nd, the 3rd contains 1,2 and then adds 3 etc.
objData.SetText Text:=Empty
objData.PutInClipboard
    
'saving down the files
    ActiveWorkbook.SaveAs Filename:= _
        "C:\Users\...\" & Format(Date, "YYYYMMDD") & "_" & Format(Time, "hhmmss") & "Insert" & "_" & Insert & ".xlsx" _
          , FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False
        ActiveWorkbook.Close

Next

MsgBox ("Files saved")

End Sub

Excel VBA 循环 剪贴板 双引号

评论

0赞 dwirony 8/11/2023
Insert现在在您的代码中没有任何作用 - 对于初学者,请从底部删除。由于您使用的是循环,因此您不需要它。如果你使用的是循环,你可以使用这个策略。我建议制作这条线,使基数每次迭代增加 1000,然后在您的行中使用它。Insert = Insert + 1ForDoFor Insert = 1 to Max_Ins Step 1000Select
0赞 AuldNoob 8/11/2023
Insert 是一个分组筛选器。最后两列(单元格值和插入)用于帮助过滤,即单元格值是行号,插入是将第 2 到 1000 行标记为 1、将 1001 到 2000 标记为 2 等的公式。然后,根据 Insert 值筛选数据
0赞 Tim Williams 8/11/2023
将数据放入数组后,您可以修改数组内容,然后将数组直接放在目标工作表上 - 无需涉及剪贴板。
0赞 AuldNoob 8/11/2023
剪贴板填充了 objData 输出(即不带引号的清理文本)。此数据不在数组中 - 是否有另一种方法可以在不使用剪贴板的情况下将 objData 放入工作表中?

答:

0赞 Tim Williams 8/11/2023 #1

您可以尝试如下操作:

Sub SaveFiles()
    Const BLOCK_SZ As Long = 1000 '# of values per block
    
    Dim ws As Worksheet, wb As Workbook, wsOut As Worksheet, v
    Dim data, block, r As Long, n As Long, ub As Long, blockNum As Long
    
    Set ws = ThisWorkbook.Sheets("SourceData")
    'pick up all data from Col AD
    data = ws.Range("AD2:AD" & ws.Cells(Rows.Count, "AD").End(xlUp).row).Value
    ub = UBound(data, 1) '# of rows
    
    Set wb = Workbooks.Add(xlWBATWorksheet) 'add single-sheet workbook
    Set wsOut = wb.Worksheets(1)
    
    n = 0
    blockNum = 0
    ReDim block(1 To BLOCK_SZ, 1 To 1) 'array for output
    For r = 1 To ub                    'loop over data and fill output array
        n = n + 1
        v = data(r, 1)
        If Not IsNumeric(v) Then
            block(n, 1) = v
        Else
            block(n, 1) = LTrim(Str(v))
        End If
        If n = BLOCK_SZ Or n = ub Then 'block is full, or end of data?
            blockNum = blockNum + 1    'increment block #
            wsOut.Range("A1").Resize(BLOCK_SZ).Value = block 'populate data block
            wb.SaveAs ThisWorkbook.Path & "\Block_" & blockNum & ".xlsx", _
                       FileFormat:=xlOpenXMLWorkbook
            ReDim block(1 To BLOCK_SZ, 1 To 1) 'clear output array
            n = 0                              'reset counter
        End If
    Next r
    wb.Close False
      
End Sub

评论

0赞 AuldNoob 8/11/2023
谢谢,但是当我复制/粘贴文本时,它再次出现不需要的双引号
0赞 Tim Williams 8/12/2023
当您在什么和什么之间复制粘贴时?您如何准确使用剪贴板中的数据?您能否展示复制粘贴时添加引号的一小部分数据示例?我们不太了解您在这里问题的根源。
0赞 AuldNoob 8/12/2023
问题始于 Excel。Col AD 是用于创建文本字符串(包括特殊字符)的公式。在 Excel 中查看时,该单元格中的所有内容都显示正确,但 Excel 中存在一个已知问题,即当您复制字符串并将其粘贴到其他应用程序中时,它会用引号括起来。代码中的“i 循环”是 VBA 中那些不需要的引号的解决方案(我在这里找到)。
0赞 Tim Williams 8/12/2023
我正在寻找问题的具体示例 - 我如何重现它以便进行测试?如果您正在查看其他具有该内容的帖子或帖子,您可以共享 URL 吗?
0赞 AuldNoob 8/12/2023
我应该补充一点,在我开始查看 VBA 删除引号之前,我的第一个想法是将 AD 列中的文本保存到 Word 而不是 Excel 中,因为显然 Word 理解不添加引号。但是,我的 IT 部门似乎阻止使用 vba 创建新的 word 文档。最终,我需要以不带引号的格式保存 10 个单独的文件