Speeding Up VB.NET application to Excel - arrays

I have written a VB.NET application in Visual Studio 2015. (first time ever had any contact with visual basic or VS). The application takes an input csv file, analyses it and splits it according to that analysis into 2 output csv files. For one of these output files, I then need to change every blank cell to have the value of zero. My prob, is that the code i've made is processing 750 input csv files to produce 1500 output files and each process in the loop is taking 5 mins meaning it's taking up to 5 days to run!! That is too long!
I'm trying to work out how to make the code run quicker. One easy first step would be in the blank cell to zero operation as i'm currently doing it cell by cell. I read that better to do via an array but i'm unsure how to code it...Can someone help?
My code now is:
Dim forceDataRangeDest, cell As Excel.Range
Dim blank As String
Dim forceDataRow, lastDataRow As Integer
'copy force data from original workbook to sheet 1 of new workbook
If ws.Range("Z" & (forceLegRowStart + 1)).Value = "Force Plate 3" Then
forceDataRow = forceDataRow + 2
forceDataRangeSrc = ws.Range("Z" & forceDataRow & ":AK" & lastDataRow)
Else forceDataRangeSrc = ws.Range("A" & forceDataRow & ":M" & lastDataRow)
End If
wsData = wbForce.Sheets("Sheet1")
wsData.Name = "Data"
forceDataRangeDest = wsData.Range("A1")
forceDataRangeSrc.Copy(forceDataRangeDest)
'insert new column A if Force Plate 3 data is one taken for the time interval data of column A
If ws.Range("Z" & (forceLegRowStart + 1)).Value = "Force Plate 3" Then
wsData.Columns("A:A").Insert(1)
'write in the Data
forceDataRangeSrc = ws.Range("A" & forceDataRow & ":A" & lastDataRow)
forceDataRangeSrc.Copy(wsData.Range("A1"))
End If
forceDataRangeDest = wsData.Range("A1:M" & ((lastDataRow - forceDataRow) + 1))
For Each cell In forceDataRangeDest
blank = cell.Value
If String.IsNullOrWhiteSpace(blank) Then
cell.Value = 0
End If
Next
It is the For Each cell at the bottom of this sample code that i think is really increasing the process time...how would i write that as an array and then write array into excel in one go?
Many thanks for any help you can give.

You could use the Range.Find and Range.FindNext methods in VBA which would be quicker than looping through all the cells. Here's an example of the VBA code:
Sub FindEmptyCells()
Dim found As Range
Dim firstCell As String
Set found = ActiveSheet.UsedRange.Find(What:="", LookAt:=xlWhole)
firstCell = found.Address
Do While Not (found Is Nothing)
Debug.Print found.Address
Set found = ActiveSheet.UsedRange.FindNext(found)
If found.Address = firstCell Then
Exit Do
End If
Loop
End Sub
EDIT: Added the code to use OP's range object
Dim found As Range
Dim firstCell As String
Set found = forceDataRangeDest.Find(What:="", LookAt:=xlWhole)
firstCell = found.Address
Do While Not (found Is Nothing)
found.Value = 0
Set found = forceDataRangeDest.FindNext(found)
If found.Address = firstCell Then
Exit Do
End If
Loop

Related

How to assign values from a 2 column array to a single column array based on a column meeting certain criteria

I need to make a macro that will gather part numbers from column A and paste them onto another sheet every 8 spaces. The catch is that I need to do this based on order codes: A11, A21, A31, B11, B21, B31, C11, C21, C31, C12, C22, C32, C13, C23, C33 (located in column B) per sheet, There are 5 sheets that are grouped as follows: Sheet 'A##' contains all codes starting with "A". Sheet 'B##' contains all codes with "B". Sheet 'C#1' contains all codes starting with C and ending with 1 and so on. This needs to be done for roughly 12000 parts. From the little knowledge I have of Excel VBA, I believe an array is the fastest way to accomplish this.
An example of what the order code looks like would be "A11", "A12", "A13" for the 3 codes needing to be sent to another sheet. I have used the wildcards symbol to limit the filtering (i.e. "A**" to represent "A13", "A23", etc.).
Below is the code I currently use to accomplish this task and with the other macros and all the looping the first run of the macro took me 1h 5 min. However, this macro will need to be run once a month and with the same workbook so I ran a second time to "refresh" the data and that took 3.5 hours. Now it won't run anymore so I have had to look for other ways to speed it up.
In the following code wb = active workbook and Sht is the sheet I want the codes onto. I wrote it this way because I am making this an excel add-in rather than just a module within the workbook.
Public Sub SetupSheetA()
Set wb = ActiveWorkbook
Set Sht = wb.Worksheets("A##")
Code = "A**"
'Grab endRow value for specific sheet designated by the order code
With wb.Worksheets("SO Hits Data Single Row")
endRow = 1 + 8 * Application.WorksheetFunction.CountIf(.Range("B4:B999999"), Code)
End With
Sht.Cells.Clear 'Clear sheet contents
'Macros
Call PartInfo
'Other macros not relevant to this question
End Sub
Public Sub PartInfo()
'***********************************************************************************************************
'Collect Part #, order code, vendor info, and WH Info
'***********************************************************************************************************
Dim j As Long, i As Long
j = Application.WorksheetFunction.CountA(wb.Sheets("SO Hits Data Single Row").Range("A1:A999999"))
With Sht
'Part #
CurrentPartRow = 2
For i = 4 To j
If Sheets("SO Hits Data Single Row").Range(Cells(i, 2).Address) Like Code Then
.Range(Cells(CurrentPartRow, 1).Address).Value = "='SO Hits Data Single Row'!" & Cells(i, 1).Address
CurrentPartRow = CurrentPartRow + 8
End If
Next i
'Order code
.Range("A3").Value = "=VLOOKUP(A2,'SO Hits Data Single Row'!$A:$B,2,FALSE)"
'Copy to Next Row
For CurrentPartRow = 10 To endRow - 7 Step 8
'Order code CopyPaste
.Range("A3").Copy Destination:=.Range(Cells(CurrentPartRow + 1, 1).Address
Next CurrentPartRow
End With
End Sub
I have tried to speed things up by saving the workbook as .xlbs which reduced the file size from 240MB to 193MB. I then deleted all the data I could get away with and removed any unnecessary formatting that further reduced the file to 163MB and then deleting the sheets the macro is pasting data onto reduced the file to 73MB.
Even with this much smaller file the macro will still hang and not respond despite running it over the entire weekend.
I also tried to filter the array using this code:
Dim arr1 As Variant, arr2 As Variant, i As Long, code As String
code = "A**" 'For any order codes containing A11, A12, A13, A21, A22, _
A23, etc
Lastrow = Sheets("SO Hits Data Single Row").Cells(Rows.Count, _
1).End(xlUp).Row
arr1 = Sheets("SO Hits Data Single Row").Range("B4:B" & Lastrow).Value
arr2 = Filter(arr1, code)
Sheets("A##").Range("a1") = arr2
But it just gives a mismatch error.
Below is a sample of the output I need to achieve.
If you have Excel 2019 or Excel 365, then you can use the built-in SORT and FILTER functions to greatly simplify things:
Public Function PartsToSheet(OrderPrefix AS String) AS Boolean
PartsToSheet = False
On Error GoTo FuncErr 'Return False if there is an error
Dim calcTMP As xlCalculation
calcTMP = Application.Calculation
'Only Calculate Formulae when we explicitly say to
Application.Calculation = xlCalculationManual
Dim wsSource AS Worksheet, wsDestination AS Worksheet
Dim lParts AS Long, lRecords AS Long
Dim adTable AS String, adOrders AS String
Set wsSource = ThisWorkbook.Worksheets("SO Hits Data Single Row")
Set wsDestination = ThisWorkbook.Worksheets(OrderPrefix & "##")
'Prepare the Destination
With wsDestination
'Deleting Rows & Columns frees up the Used Range, freeing more memory than Clear does
.Range(.Cells(1, 1), .Range(.Rows.Count, 1)).EntireRow.Delete
.Range(.Cells(1, 1), .Range(1, .Columns.Count)).EntireColumn.Delete
End With
lParts = Application.CountA(wsSource.Columns(1))
lRecords = Application.CountIf(wsSource.Columns(2), OrderPrefix & "*")
adTable = wsSource.Range(wsSource.Cells(1, 1),wsSource.Cells(lParts, 2)).Address(True, True, xlA1, True)
adOrders = wsSource.Range(wsSource.Cells(1, 2),wsSource.Cells(lParts, 2)).Address(True, True, xlA1, True)
If lRecords > 0 Then 'If there are Order Codes for this Sheet
wsDestination.Range(wsDestination.Cells(2, 1), wsDestination.Cells(8 * lRecords - 6)).Formula = _
"=IF(MOD(ROW()+6,8)>0, """", INDEX(SORT(" & _
"FILTER(" & adTable & ", LEFT(" & adOrders & ", 1)=""" & OrderPrefix & """)" & _
", 2), (ROW()+6)/8, 1))"
wsDestination.Columns(1).Calculate 'Explicitly calculate formulae
wsDestination.Range(wsDestination.Cells(2, 1), wsDestination.Cells(8 * lRecords - 6)).Value = _
wsDestination.Range(wsDestination.Cells(2, 1), wsDestination.Cells(8 * lRecords - 6)).Value
End If
PartsToSheet = True 'Success!
FuncErr:
On Error GoTo -1 'Clear any errors in the handler
Application.Calculation = calcTMP
End Function
Basically, we fill the first column of the destination sheet with a function that will be blank for 7 lines (IF(MOD(ROW()+6,8)>0,), then provide the next entry (INDEX(.., (ROW()+6)/8, 1)) in an array that we get by FILTERing for the Prefix, and SORTing on the Order Code.
Then we "flatten" the result by converting it from dynamic formulae into static values.
So, I have found that an array was in fact the best way to approach this. However, The file size was clearly a major issue, and I found it was due to blank cells being included in the current selection. Once I fixed that the macro ran quicker but still took too long. I ended up writing code to save the data to an array and then filter it later in a similar fashion to the following.
Sub Example()
Dim arr1 As Variant, arr2(10000) As Variant, i As Long, j As Long, k As Long, Filter As String
Application.ScreenUpdating = False 'Freeze screen while macro runs
Application.EnableEvents = False 'Disable popups
Application.Calculation = xlManual 'Disable Sheet calcs
Filter = "A**"
arr1 = ActiveWorkbook.Worksheets("Sheet1").Range("A4:B12000").Value
j= Application.WorksheetFunction.CountA(wb.Sheets("SO Hits Data Single Row").Range("A1:A20000"))
For i = 1 To j
If arr1(i, 2) Like Filter Then
arr2(k) = arr1(i, 1)
arr2(k + 1) = ""
arr2(k + 2) = ""
arr2(k + 3) = ""
arr2(k + 4) = ""
arr2(k + 5) = ""
arr2(k + 6) = ""
arr2(k + 7) = ""
k = k + 8 'This was so I could adjust for the blank spaces I needed between each value in the array
End If
Next i
Application.ScreenUpdating = True 'Unfreeze screen
Application.Calculation = xlAutomatic 'Enable Sheet calcs
Application.EnableEvents = True 'Enable popups
End Sub
The above code is a little more specific to my situation but below is a more general form for any future viewers.
Sub Example()
Dim arr1 As Variant, arr2(10000) As Variant, i As Long, j As Long, k As Long, Filter As String
Application.ScreenUpdating = False 'Freeze screen while macro runs
Application.EnableEvents = False 'Disable popups
Application.Calculation = xlManual 'Disable Sheet calcs
Filter = "A**" 'This is where you would put your filter instead of "A**"
arr1 = ActiveWorkbook.Worksheets("Sheet1").Range("A4:B12000").Value
j= Application.WorksheetFunction.CountA(wb.Sheets("SO Hits Data Single Row").Range("A1:A20000"))
For i = 1 To j
If arr1(i, 2) Like Filter Then
arr2(k) = arr1(i, 1)
End If
Next i
Application.ScreenUpdating = True 'Unfreeze screen
Application.Calculation = xlAutomatic 'Enable Sheet calcs
Application.EnableEvents = True 'Enable popups
End Sub

Saving an array to new workbook

Scenario: I have a workbook with multiple worksheets. I am trying to use a function (called within a sub) to export arrays with data from certain worksheets. The arrays are created before the function with the content from the worksheet with:
If ws.Name = "AA" Then
expaa = ws.UsedRange.Value
End if
where expaa is previously defined as variant.
The function I am using apparently finishes running, but the output on the new file saved is weird: instead of having one row of headers, the first row is split into 2 for some reason (all the others remain the same).
This is the function I am using:
Function Exporter(arr As Variant, y As String, OutPath As String) As Variant
Dim lrow As Long, lColumn As Long
Dim w2 As Workbook
Dim d As Date
Workbooks.Add
Set w2 = ActiveWorkbook
w2.Worksheets(1).Range("A1").Resize(UBound(arr, 1), UBound(arr, 2)) = arr
Application.DisplayAlerts = False
w2.SaveAs Filename:=OutPath & "\" & y, FileFormat:=6
Application.DisplayAlerts = True
w2.Close True
End Function
Which I call from the main sub with:
If aa_name <> "" Then
Exporter expaa , "aa_OK", wbpath
End If
where aa_name is the name of the file used to retrieve the path.
Obs: The wbpath variable is a string with the path of my main workbook (therefore the new file is saved at the same location).
Question: What may be causing the first row of my output to be split? How can that be fixed?
Obs2: I know this can be done with copy procedure, and looping through the array and so on. I even got it to work with other methods. This post is only to understand what I am doing wrong with the current code.
Obs3: Regarding the data that is going to be passed: it is a matrix of days, identifiers and data, ex:
Item1 Item2 Item3
01/01/2000 1 1 2
02/01/2000 1 2 1
03/01/2000 2 2 2
with around 2000 rows and 3000 columns.
UPDATE: After retesting the code multiple times, It appears that the data of the first row only gets split when the file is save as csv (when the array is pasted, the output is normal). Any idea on what may be the cause for that?
I know this is old but here is my solution for the googlers. This accepts an array and creates a CSV at a path you define. Its probably not perfect but it has worked so far for me.
Option Explicit
Option Private Module
Public Function SaveTextToFile(ByVal targetarray As Variant, ByVal filepath As String) As Boolean
On Error GoTo CouldNotMakeFile
Dim fso As FileSystemObject
Set fso = New FileSystemObject
Dim fileStream As TextStream
' Here the actual file is created and opened for write access
Set fileStream = fso.CreateTextFile(filepath)
' Write something to the file
Dim Row As Long, Col As Long
For Row = LBound(targetarray, 1) To UBound(targetarray, 1)
For Col = LBound(targetarray, 2) To UBound(targetarray, 2)
fileStream.Write StringCompliance(targetarray(Row, Col)) & IIf(Col = UBound(targetarray, 2), "", ",")
Next Col
fileStream.WriteBlankLines 1
Next Row
' Close it, so it is not locked anymore
fileStream.Close
' Here is another great method of the FileSystemObject that checks if a file exists
If fso.FileExists(filepath) Then
SaveTextToFile = True
End If
CouldNotMakeFile:
End Function
Private Function StringCompliance(ByVal InputString As String) As String
Dim CurrentString As String
CurrentString = InputString
'Test if string has qoutes
If InStr(CurrentString, Chr$(34)) > 0 Then
CurrentString = Chr$(34) & Replace(CurrentString, Chr$(34), Chr$(34) & Chr$(34)) & Chr$(34)
StringCompliance = True
Else
'Tets if string has commas or line breaks
If InStr(CurrentString, ",") > 0 Or InStr(CurrentString, vbLf) > 0 Then
CurrentString = Chr$(34) & CurrentString & Chr$(34)
Else
StringCompliance = False
End If
End If
StringCompliance = CurrentString
End Function

VBA Live-filter listbox via textbox & save multiple selections from listbox in one cell

Hello again community,
After I got so much help from you with my last Problem, that promted me to rework the entire code in a more efficient manner, I would like to ask two more questions regarding the same Project.
(1) I would like to implement a live-filter in my listbox CGList1, which is connected to the textbox SearchCGList1. Whenever someone types in the textbox, the results in the listbox should be adjusted. I found this Article on your website, as well as this Article 3 on an external Webpage. However, due to my very limited skills, I have not been able to adapt it properly. More later.
(2) After multiple items from the same listbox CGList1 have been transferred to the second listbox CGList2 via a button (which works like a treat), I would like to save them in the same cell (Range "BM") on my Worksheet Meta DB. For this problem I also used Google extensively and tried to adapt the findings (see links below) for my code - without success.
I hope that the Patient ones amongst you can help me out once again, in the knowledge that I am trying to learn as much as possible. My Problem is that for a lot of things, I simply do not know what to look for.
My preliminary code for Problem 1:
CGList1 and CGList2 have no code. They are populated in the Userform_Initialize sub via:
'Fill Material Groups Listbox1 dynamically
Dim cell As Range
Dim rng As Range
With ThisWorkbook.Sheets("Commodity Groups")
'Range to 500 in order to allow for further additions
Set rng = .Range("A2", .Range("A500").End(xlUp))
End With
Me.CGList1.ColumnWidths = "20;80"
For Each cell In rng.Cells
'Filter out blanks
If cell <> "" Then
With Me.CGList1
.AddItem cell.value
.List(.ListCount - 1, 1) = cell.Offset(0, 1).value
End With
End If
Next cell
I cannot just use .AddItem and then filter through the columns like you find in many examples online because it needs to be dynamic and there are many blanks in between the selection items on the Worksheet.
The buttons:
Private Sub addCGbutton_Click()
For i = 0 To CGList1.ListCount - 1
If CGList1.Selected(i) = True Then
'Copy only CG Name, not respective number/letter combination (only more work to cut out when working with it later)
CGList2.AddItem CGList1.List(i, 1)
End If
Next i
End Sub
'Delete selected Commodity Groups from List 2 for re-selection
Private Sub delCGbutton_Click()
Dim counter As Integer
counter = 0
For i = 0 To CGList2.ListCount - 1
If CGList2.Selected(i - counter) Then
CGList2.RemoveItem (i - counter)
counter = counter + 1
End If
Next i
End Sub
After a lot of trial and failure trying to adapt the linked approaches from other people, I tried something more simple:
Private Sub SearchCGList1_Change()
'Only show with textbox matching items in CGList1 (filter)
Dim strSQL As String
strSQL = "SELECT fieldname FROM table WHERE fieldname = "
strSQL = strSQL & "'" & Me!SearchCGList1 & "*'"
strSQL = strSQL & " ORDER BY fieldname;"
Me!SearchCGList1.RowSource = strSQL
End Sub
But without success.
Regarding Problem 2:
To save the multiple selections from CGList2 in Range BM on Worksheet "Meta DB", I toyed around a lot and my last try was:
Save multiple selections from Commodity Group List 2 to the same cell in Excel
Dim listItems As String, c As Long
With CGList2
For c = 0 To .ListCount - 1
If .Selected(c) Then listItems = listItems & .List(c) & ", "
Next c
End With
Range("BM") = Left(listItems, Len(listItems) - 2)
Usually, all my other UserForm entries are saved with a single command button in the following fasion:
Private Sub CommandButton21_Click()
'Application.ScreenUpdating = False
'Define all relevant WBs we will be working with
Dim wbInput As Workbook
Dim wb As Workbook
Set wb = ActiveWorkbook
Dim ws As Worksheet
Set ws = wb.Worksheets("Meta DB")
Dim LastRow As Long
'Save Userform Inputs
With ws
.Activate
LastRow = ws.Range("A" & Rows.Count).End(xlUp).row + 1
.
.
Range("BK" & LastRow).value = Me.payinfo90
Range("BL" & LastRow).value = Me.payinfo90more
'Risk Management - Residual Information
Range("BM" & LastRow).value = Me.CGList2
Range("BN" & LastRow).value = Me.suppsince
.
.
End With
End Sub
Again, I thank everyone who took the time to read my post and answer with tips on what to improve.
Everyone have a great day.
Using a helper column with array formula.
So if say you had your data for the 1st list box in a1:a10 and the selection from this listbox is placed in D1, the 2nd complete listbox selections are in B1:B10, but not used, then in E1:E10, I have the following array formula filled down, so you would populate the 2nd listbox off the helper column E.
Beginning with
=INDEX($B$1:$B$10,SMALL(IF(LEFT($B$1:$B$10,LEN($D$1))=$D$1,ROW($B$1:$B$10),""),ROWS($E$1:$E1)),1)
Containing
=INDEX($B$1:$B$10,SMALL(IF(NOT(ISERR(SEARCH($D$1,$B$1:$B$10))),ROW($B$1:$B$10)),ROWS($E$1:E1)),1)
You need to press CTRL SHIFT and ENTER for array formula.

VBA Subscript out of Range Error appearing after Collection contains so many elements

I'm really struggling to find what's generating the 'Subscript Out Of Range' error in my code below. What I'm trying to do with said code is to read data from text files having a time stamp within 90 days of the current date. To collect this data, I'm reading each file line by line, storing that data into a split array, then populating two collections with specific rows of the split array. This code works fine with another application of it that I'm using to retrieve data only from a specific job set. The code in the aforementioned application appears to be working fine until I reach one particular file which doesn't differ in any way (formatting, content, or otherwise) from previous files that were successfully read. It seems to me that I'm reaching the size limit of each collection but I'm not sure. Below is my code:
Private Sub Analyze_90Day_Data_Click()
Application.ScreenUpdating = False
Data_Selection_21075A.Hide
'Declare Variables
Dim FFFile As String
Dim SplitData() As String
Dim DateIter As Long
Dim CurrentDate As Date
Dim FileDate As Date
Dim colSN As String
Dim colSet As String
Dim KPCDate As Date
Dim CMMArray() As Variant
'Remove old data from 21075A KPC
LastRow = Sheets("21075A KPC").Range("G65536").End(xlUp).Row
For SheetRow = 12 To LastRow
Sheets("21075A KPC").Range("G" & SheetRow & ":H" & SheetRow).ClearContents
Next SheetRow
'Populate 21075A KPC with new data
CurrentDate = Date
KPCDate = DateAdd("d", -90, CurrentDate)
CMMArray = Array("Inspcmm1", "Inspcmm2")
For CMM = LBound(CMMArray) To UBound(CMMArray)
With New Scripting.FileSystemObject
CMMFolder = "\\" & CMMArray(CMM) & "\cmm\21075A\OP290"
On Error GoTo ResumeIter
Set CMMFold = .GetFolder(CMMFolder)
For Each SetFolder In CMMFold.SubFolders
FFFile = SetFolder & "\21075A-030-FINALFLOWTOT " & SetFolder.Name & ".txt"
MsgBox SetFolder.Name
FileDate = FileDateTime(FFFile)
If FileDate >= KPCDate Then
LineIter = 0
With .OpenTextFile(FFFile, ForReading)
Do Until .AtEndOfStream
LineIter = LineIter + 1
LineData = .ReadLine
SplitData = Split(LineData)
'Extracting Serial Number
strSN.Add SplitData(0)
'Extracting Final Flow Value
strFF.Add SplitData(2)
Loop
.Close
End With
End If
Next SetFolder
End With
ResumeIter:
Next CMM
If strSN.Count = 0 Then
MsgBox "Neither Brown & Sharpe is online."
Exit Sub
Else
SheetRow = 12
For SNIter = 1 To strSN.Count Step 1
With Sheets("21075A KPC")
.Range("G" & SheetRow).Value = strSN.Item(SNIter)
.Range("H" & SheetRow).Value = strFF.Item(SNIter)
End With
SheetRow = SheetRow + 1
Next SNIter
LastRow = Sheets("21075A KPC").Range("G65536").End(xlUp).Row
With Sheets("21075A KPC")
'Calculate & Populate Means
.Range("H5") = WorksheetFunction.Average(.Range("H12:H" & LastRow))
'Calculate & Populate Standard Deviations
.Range("H6") = WorksheetFunction.StDev(.Range("H12:H" & LastRow))
'Populate 90-Day Reporting Period
.Range("F3") = KPCDate
.Range("F4") = CurrentDate
End With
End If
End Sub
All variables not declared in the above procedure have already been publicly declared. Thanks for looking into this. Please let me know if you need anything else from me.
I figured out that the SplitData array wasn't getting emptied and was consequently reaching its size limit, causing the Subscript Out of Range Error. I added the code line 'Erase SplitData()' after the code line 'Do Until .AtEndOfStream' and this emptied the SplitData array each time to prevent the accumulation of unnecessary data.

Split function not creating array()

I've worked this code over a few times, but I always seem to have a problem with the Split statement passing my array. Here's a piece of code that's not working and I can't figure out why
Private Sub parseCSV()
'Parse "Notes" column and return Moods/Keywords to their apropriate cells
Dim CSV As String
Dim fullArray() As String
Dim lRow As Long
Dim Keywords As String
Dim Moods As String
Dim i As Long
lRow = ActiveSheet().Range("BL" & ActiveSheet().Rows.Count).End(xlUp).Row
For i = 3 To lRow
CSV = ActiveSheet.Range("BL" & i)
fullArray() = Split(CSV, Chr(10))
ActiveSheet.Range("CE" & i).Value = fullArray(3)
ActiveSheet.Range("CD" & i).Value = fullArray(2)
Next i
End Sub
It gives an Err-9, value out of range. It's so weird. I've tested it a bunch of different ways and this is what I've found.
It will return the 1st piece of data in the array. I can change my delimiter to any thing i want and get exactly what I would expect in the first place of the array returned, if I change my code to fullArray(). I've also tried using Application.Index(fullArray, 1, 2), no dice. I've tried using various combination of array coordinates and variant/string combos. Nothing. Please help, I would greatly appreciate it.
Here is an example of what is contained in the cell being split;
To License Contact, licensing#primarywavemusic.com, 212.661.6990/310.247.8630
Go, White, Know
Happy, Rock, Upbeat, Catchy
You need to test the UBound first to verify there are actually 3 lines. A UBound(fullArray) of 2 indicates three lines. This is an example of a zero based array. The third line ends up in fullArray(2).
If your input is three lines long you can get the split using:
fullArray(0)
fullArray(1)
fullArray(2)
Here is your adjusted code:
For i = 3 To lRow
If UBound(fullArray) >= 2 Then
CSV = ActiveSheet.Range("BL" & i)
fullArray() = Split(CSV, Chr(10))
ActiveSheet.Range("CE" & i).Value = fullArray(2) 'enter third line
ActiveSheet.Range("CD" & i).Value = fullArray(1) 'enter second line
Else
'this will output the cell address of any cell that
'doesn't have 3 lines within the cell
Debug.Print ActiveSheet.Range("BL" & i).Address
End If
Next i

Resources