0

Setup

My source Excel file has 10k rows of 32 columns. I need to break this down into 10 files of 1k each and extract one specific column, AD, for further processing.

Column AD is is a text string containing special characters which I need to preserve, and I'm trying to remove the unwanted double quotes from the filtered string for pasting into another application later.

Problem Statement

Only the first file is saving correctly. The second file repeats the information from the first loop as well as updating it with the filtered rows from the second loop, the third file contains data from the first, second and third loops etc. That is, by the time we get to the 10th file, I have 10k rows instead of 1k

Question

How do I clear the clipboard between loops so that both the DataArray and the Clipboard are emptied, and refilled afresh with the filtered text for that specific loop?

My (edited with explanations) VBA is:

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

AuldNoob
  • 5
  • 5
  • `Insert` is serving no purpose in your code right now - for starters, get rid of `Insert = Insert + 1` at the bottom. Since you're using a `For` loop you don't need this. If you were using `Do` loop, you could use this strategy. I'd recommend making the line `For Insert = 1 to Max_Ins Step 1000` so that the base number increments 1000 each iteration, then use that in your `Select` lines. – dwirony Aug 10 '23 at 17:55
  • Insert is a grouping filter. The last two columns (Cell Value and Insert) are used to help with the filtering i.e. Cell Value is the Row Number and Insert is a formula to label rows 2 to 1000 as 1, 1001 to 2000 as 2 etc. The data is then filtered on the Insert valu – AuldNoob Aug 10 '23 at 18:11
  • Once you have the data in an array you can modify the array contents and then place the array directly on the destination worksheet - there's no need to involve the clipboard. – Tim Williams Aug 10 '23 at 18:47
  • The clipboard is populated with the objData output (i.e. the cleansed text without the quotes). This data isn't in the array - is there another way to get the objData into the worksheets without using the clipboard? – AuldNoob Aug 11 '23 at 10:44

1 Answers1

0

You could try something like this:

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
Tim Williams
  • 154,628
  • 8
  • 97
  • 125
  • Thank you, however when I copy/paste the text it has the unwanted double quotes again – AuldNoob Aug 11 '23 at 10:09
  • When you copy paste between what and what? How do you use the data from the clipboard exactly? Can you show a small sample of the data where quotes are added when copy-pasted? We don't have much visibility on what seems to be the root of your problem here. – Tim Williams Aug 11 '23 at 16:07
  • The problem begins with Excel. Col AD is a formula to create a text string, including special characters. Everything in that cell appears correct when viewed in Excel, but there's a known issue within Excel that when you copy the string and paste it into other applications, it's then wrapped in quote marks. The "i loop" in the code is the solution to those unwanted quotes within VBA (which I found on here). – AuldNoob Aug 11 '23 at 17:59
  • I'm looking for a concrete example of the problem - how can I reproduce it so I can test? If you're looking at some other thread or post which has that, can you share the URL? – Tim Williams Aug 11 '23 at 18:04
  • I should add that, before I started looking at VBA to remove the quotes, my first idea was to save the text from Column AD into Word rather than Excel as, apparently, Word understands not to add the quotes. However, my IT dept seems to have a block an using vba to create new word docs. Ultimately I need to have 10 separate files saved in a format without the quote marks – AuldNoob Aug 11 '23 at 18:11
  • If you open an excel file and place random characters into cells a b and c, then use a formula in cell D like =A1&"ABC"&Chr(13)&B1&"_"&chr(10)&C1 you'll see that the string appears fine in Excel, bit of you copy that into notepad it'll be wrapped in quotes. – AuldNoob Aug 11 '23 at 18:17
  • This thread has more info on the problem: https://stackoverflow.com/questions/24910288/leave-out-quotes-when-copying-from-cell – AuldNoob Aug 11 '23 at 18:19
  • Thanks that's what I was looking for – Tim Williams Aug 11 '23 at 18:20
  • So for putting the data in the clipboard, that's in *addition* to splitting it into separate files? How can you later use the clipboard content for (eg) the first block, if it's later overwritten by the second one? – Tim Williams Aug 11 '23 at 18:26
  • My thought process was to filter the source file, copy the filtered data and paste into a new file, copy that data into an array, loop through and remove the quotes, set results to clipboard, delete the original pasted data, paste the processed data from the clipboard, save the file, clear the clipboard and repeat. Once file 1 is saved I've no need for that block to be retained but it's not clearing correctly, so file 2 has block 1 and block 2. – AuldNoob Aug 11 '23 at 18:34
  • So you're just pasting data back into Excel and that's it? That's the only way it can work in your loop, since it can't stop and wait for you to paste elsewhere... I'm feeling a bit dense because I'm having problems following your workflow. – Tim Williams Aug 11 '23 at 18:52
  • It's my fault for not explaining properly. But, yeah I'm copying the "standard" data from Excel, using the "i loop" which I found on here to "re-copy" that same data but, crucially, without the quotes this time and then paste *that* data back. Essentially I'm trying to avoid manually copying from Excel, pasting to Word (which removes the quotes automatically), then pasting back to Excel to save the file. Everything is working apart from being unable to fully clear the clipboard so file 1 is perfect, but file 2 contains file 1 AND file 2 data, leading to duplication. Thanks for your help btw – AuldNoob Aug 11 '23 at 19:11
  • Looks like you never clear `concat` between iterations? – Tim Williams Aug 11 '23 at 20:07
  • Thank you! That's it and it's now working on my test file (with a smaller sample set). However, on the true sample set I'm getting errors on some cells re 'unable to put in clipboard' The cell values are ok as near-identical ones are already processed and if I reorder things to test the problematic cells process fine. Do you think there's a character/data limit in using the the clipboard this way? – AuldNoob Aug 11 '23 at 21:05
  • It's difficult to say without some actual data to test with, but lately I've given up on the `DataObject` method of putting text in the clipboard, since some recent changes seem to have made it quite unreliable. Using the Windows API is more robust. https://learn.microsoft.com/en-us/office/vba/access/concepts/windows-api/send-information-to-the-clipboard – Tim Williams Aug 11 '23 at 21:26
  • Getting out of my comfort zone now I'm afraid :-). I've found a solution though using your code so thank you for that. Although IT have blocked Word macros for running, they've not blocked Outlook so I can use your code to generate the Excel files, then save the text as outlook messages which then removes the quotes. I can't upvote your answer as I don't have enough credit on the site but I'd like to say thanks for your help and your patience - much appreciated. – AuldNoob Aug 12 '23 at 10:22
  • OK - good to hear you got through to a solution. – Tim Williams Aug 12 '23 at 16:20