so what I need to do is fill an array using an InputBox, then but that in an array, sort it alphabetically and then output it to the current word document. I have it almost most complete, the issue is it is only outputting the last word to the document. Im guessing my loop is wrong but I cannot find VBA documentation to do this to save my life. Thank you
Option Explicit
This is the main sub that declares the array
Sub Main()
Dim ListArr() As String
ListArr = Get_Input_List()
Call Bubble_Sort_Ascending(ListArr)
Call Output_List_To_Document(ListArr)
End Sub
Function to get input and fill array
Function Get_Input_List() As String()
Dim list As String
list = InputBox("Please enter words to sort separated with a comma and no spaces", "Words")
Get_Input_List = Split(list, ",")
End Function
Sorts the array alphabetically
Sub Bubble_Sort_Ascending(listNewArray() As String)
Dim SrtTemp As Variant
Dim inputWord As Variant
Dim i As Long
Dim j As Long
'Alphabetize Sheet Names in Array List
For i = LBound(listNewArray) To UBound(listNewArray)
For j = i To UBound(listNewArray)
If listNewArray(i) > listNewArray(j) Then
SrtTemp = listNewArray(j)
listNewArray(j) = listNewArray(i)
listNewArray(i) = SrtTemp
End If
Next j
Next i
End Sub
This is the problem, I cannot output the whole array to the word document. I have found plenty of documentation on how to do this into an excel spreadsheet but almost nothing for word.
Sub Output_List_To_Document(newListArray() As String)
Dim inputWord As Variant
Dim i As Long
Dim j As Long
For i = LBound(newListArray) To UBound(newListArray)
For j = i To UBound(newListArray)
For Each inputWord In newListArray
ActiveDocument.Range = inputWord & vbCrLf
Next
Next j
Next i
End Sub
You're over-writing ActiveDocument.Range each time through the loop. If you want to append to the end of it, you need to collapse the range to it's ending position:
Sub Output_List_To_Document(newListArray() As String)
Dim inputWord As Variant
Dim i As Long
Dim j As Long
Dim insertPos As Range
Set insertPos = ActiveDocument.Range
For i = LBound(newListArray) To UBound(newListArray)
For j = i To UBound(newListArray)
For Each inputWord In newListArray
insertPos.Collapse wdCollapseEnd
insertPos = inputWord & vbCrLf
Next
Next j
Next i
End Sub
Note - It isn't clear why you're looping through the array with 3 nested loops. If you only need to write each word once, I suspect you're really looking for something more like this:
Sub Output_List_To_Document(newListArray() As String)
Dim insertPos As Range
Set insertPos = ActiveDocument.Range
Dim inputWord As Variant
For Each inputWord In newListArray
insertPos.Collapse wdCollapseEnd 'Value 0, Can ignore writing it as well
insertPos = inputWord & vbCrLf
Next
End Sub
Related
I have code to ask a user for a series of codes that then creates a single-dimensional array like this:
Dim strDaysTimes As String
Dim arrDaysTimes() As String
strDaysTimes = InputBox("What days and times do you want to schedule meetings for? (write as 6c,7b)", "Enter Days and Times")
arrDaysTimes() = Split(strDaysTimes, ",")
The number of inputs is not defined but the format is. It could be "6c,7b" or "5a,6b,7b".
I want to convert this into a multi-dimensional array that would carry the values like this (one dimension has the number portion and the other has the letter portion):
5 a
6 b
7 b
I know that I need to use a nested For...Next statements to process multidimensional arrays, but I would appreciate any suggestions.
Use ReDim:
Public Function DivideArray()
Dim strDaysTimes As String
Dim arrDaysTimes() As String
Dim DaysTimes() As String
Dim Index As Integer
strDaysTimes = InputBox("What days and times do you want to schedule meetings for? (write as 6c,7b)", "Enter Days and Times")
arrDaysTimes() = Split(strDaysTimes, ",")
ReDim DaysTimes(UBound(arrDaysTimes) - LBound(arrDaysTimes) + 1, 0 To 1)
For Index = LBound(arrDaysTimes) To UBound(arrDaysTimes)
DaysTimes(Index, 0) = Left(LTrim(arrDaysTimes(Index)), 1)
DaysTimes(Index, 1) = Right(RTrim(arrDaysTimes(Index)), 1)
Next
For Index = LBound(arrDaysTimes) To UBound(arrDaysTimes)
Debug.Print DaysTimes(Index, 0), DaysTimes(Index, 1)
Next
End Function
Input example:
a7, b8, c9
Output:
a 7
b 8
c 9
Just for the sake of the art an alternative to #Gustav 's approach with the bonus that it returns token lengths greater than 1, too.
Furthermore it profits from the fact that the Val() function is able to return
a) the starting numeric value from an input string and
b) the closing string by a split via the above numeric value as delimiter.
Public Function tokenize(ByVal s As String)
Dim arr() As String
arr() = Split(Trim(s), ",")
Dim tmp() As String
ReDim tmp(0 To UBound(arr) - LBound(arr), 0 To 1)
Dim i As Long
For i = LBound(arr) To UBound(arr)
Dim num: num = Val(arr(i))
tmp(i, 0) = num
tmp(i, 1) = Split(arr(i), num)(1)
Next
tokenize = tmp
End Function
Example call
Sub testTokenize()
'0. Get input string (e.g. "6c,7b")
Dim strDaysTimes As String
strDaysTimes = InputBox( _
"What days and times do you want to schedule meetings for? (write as 6c,7b)", _
"Enter Days and Times", _
"6c,7b")
'1. Call help function
Dim results As Variant
results = tokenize(strDaysTimes) ' << function tokenize()
'2. Show results in VB Editor's immediate window
Dim i As Long
For i = LBound(results) To UBound(results)
Debug.Print results(i, 0), results(i, 1)
Next
End Sub
The following code will help you get there.
The GetDaysAndTimes function will return a Jagged array (i.e. an array of arrays). This means that to get the Day and Time of Item 3 you would use ArrayName(2)(0) and ArrayName(2)(1) where arrayname is the name of the array you are using (arrayDaysTimes?)
The function SplitAlphaNumString allows users to enter codes such as AB23.
Option Explicit
' This function takes the string returned by your input box
Public Function GetDaysAndTimes(ByRef ipString As String) As Variant
Dim myItems As Variant
myItems = VBA.Split(ipString, ",")
Dim myDayTimes As Variant
Dim myindex As Long
For myindex = LBound(myItems) To UBound(myItems)
myDayTimes(myindex) = SplitAlphaNumString(myItems(myindex))
Next
GetDaysAndTimes = myDayTimes
End Function
Public Function SplitAlphaNumString(ByVal ipString As String) As Variant
Dim myindex As Long
For myindex = 1 To VBA.Len(ipString)
If VBA.Asc(VBA.Mid(ipString, myindex, 1)) < 58 Then
Dim myAlphas As String
myAlphas = VBA.Mid(ipString, 1, myindex - 1)
Dim myNums As String
myNums = VBA.Mid(ipString, myindex)
SplitAlphaNumString = Array(myAlphas, myNums)
Exit Function
End If
Next
End Function
Sub Test()
Dim myArray As Variant
myArray = SplitAlphaNumString("D5")
Debug.Print myArray(0), myArray(1)
End Sub
Let's say I have something like "1-34-52", I want to split them into an array, however, while Test1 works, it gives me an String() type array. How do I put the numbers in "1-34-52" into a Long() type array? Can I redim type of an array in VBA?
Sub Test1()
Dim arr As Variant
arr = Split("1-34-52", "-")
Debug.Print TypeName(arr), TypeName(arr(0))
End Sub
Sub Test2()
Dim arr() As Long
arr = Split("1-34-52") 'You get type mismatch error
End Sub
You can Redim an array of Variants. Since Variants can hold integer values, there is no problem:
Sub dural()
ary = Split("1-34-52", "-")
ReDim lary(0 To UBound(ary))
For i = 0 To UBound(ary)
lary(i) = CLng(ary(i))
Next i
End Sub
Note:
Sub dural()
ary = Split("1-34-52", "-")
Dim lary() As Long
ReDim lary(0 To UBound(ary))
For i = 0 To UBound(ary)
lary(i) = CLng(ary(i))
Next i
End Sub
will also work.
You can loop through the array and populate a new one:
Sub Test1()
Dim arr As Variant, LongArr() As Long, X As Long
arr = Split("1-34-52", "-")
ReDim LongArr(UBound(arr))
For X = LBound(arr) To UBound(arr)
LongArr(X) = CLng(arr(X))
Next
Debug.Print TypeName(arr), TypeName(arr(0))
Debug.Print TypeName(LongArr), TypeName(LongArr(0))
End Sub
I am creating a workbook that will copy and paste data from a source worksheet to multiple other worksheets depending upon values in a column. However, once I start the macro, Excel enters a not responding state. I am operating on anywhere from 4000 to 500,000 rows, but only 4 columns. When I only have ~4000 rows, it works pretty fast (3 seconds). When I have ~30,000 rows, Excel enters a not responding state for ~10 seconds, but then finishes. I didn't wait long enough for the 300,000 row test.
My thought process to do this would be to sort all of the data based upon the strings in column B, put all of column B (which contains the strings I am searching though) into an array, then pull all of the unique strings out into another array. For example, if column B held "Search" in rows 1-200, and "Create" in rows 201-500, the macro will search through the rows and the second array (lets call it Scenario) would end up holding two values, "Search" and "Create".
During the searching, I also created two parallel arrays that correspond with the Scenario array which would hold the beginning and ending rows for that scenario. After that, I would just loop through the values in the parallel arrays and copy/paste from the source worksheet to the other worksheets.
NOTE: The sort works fine
Is there a way to make this faster?
Here is the code:
Allocate Data
Sub AllocateData()
Dim scenarioRange As String 'To hold the composite range
Dim parallelScenarioName() As String 'Holds the unique scenario names
Dim parallelScenarioStart() As Long 'Holds the starting row of the scenario
Dim parallelScenarioEnd() As Long 'Holds the ending row of the scenario
Sheets("raw").Activate 'Raw is the source worksheet
'Populates the parallel scenario arrays
Call GetScenarioList(parallelScenarioName, parallelScenarioStart, parallelScenarioEnd)
'Loops through the scenario parallel array and coes the copy and paste to other worksheets
'Workseets are named the same as the scenarios
For intPosition = LBound(parallelScenarioName) To (UBound(parallelScenarioName) - 1)
scenarioRange = "A" & parallelScenarioStart(intPosition) & ":" & "D" & parallelScenarioEnd(intPosition)
Range(scenarioRange).Select
Selection.Copy
Worksheets(parallelScenarioName(intPosition)).Activate
Range("A1").Select
ActiveSheet.Paste
Sheets("raw").Activate
Next
End Sub
GetScenarioList
Sub GetScenarioList(ByRef parallelScenarioName() As String, ByRef parallelScenarioStart() As Long, ByRef parallelScenarioEnd() As Long)
Dim scenarioName As Variant
Dim TotalRows As Long
Dim arraySize As Long
arraySize = 1
'Prep the parallel array for scenario name with the first value
ReDim parallelScenarioStart(1)
ReDim parallelScenarioName(1)
parallelScenarioStart(0) = 1 'First spot on the scenario start will be row 1
'Prep the first scenario name
'Sometimes a number will be attached on the end of the scenario name delimited by a period. Ignore it.
If (InStr(Cells(1, 2).Text, ".") <> 0) Then
parallelScenarioName(0) = Left(Cells(1, 2).Text, InStr(Cells(1, 2).Text, ".") - 1)
Else
parallelScenarioName(0) = Cells(1, 2).Text
End If
'Get the total amount of rows
TotalRows = Rows(Rows.Count).End(xlUp).row
'Loop through all of the rows
For i = 1 To TotalRows
'Sometimes a number will be attached on the end of the scenario name delimited by a period. Ignore it.
If (InStr(Cells(i, 2).Text, ".") <> 0) Then
scenarioName = Left(Cells(i, 2).Text, InStr(Cells(i, 2).Text, ".") - 1)
Else
scenarioName = Cells(i, 2).Text
End If
'If the scenario name is not contained in the unique array
If IsNotInArray(scenarioName, parallelScenarioName) Then
Call AddScenarioEndRow(i, arraySize, parallelScenarioEnd)
Call AddNewScenarioToParallelArray(scenarioName, arraySize, parallelScenarioName)
Call AddNewScenarioStartRow(i, arraySize, parallelScenarioStart)
End If
Next
'Cleanup. The above code did not cover the ending row of the last scenario
Call AddScenarioEndRow(TotalRows + 1, arraySize, parallelScenarioEnd)
End Sub
IsNotInArray
Function IsNotInArray(stringToBeFound As Variant, ByRef parallelScenarioName() As String) As Boolean
IsNotInArray = Not (UBound(Filter(parallelScenarioName, stringToBeFound)) > -1)
End Function
Parallel Arrays
Sub AddNewScenarioToParallelArray(str As Variant, arraySize As Long, ByRef parallelScenarioName() As String)
arraySize = UBound(parallelScenarioName) + 1
ReDim Preserve parallelScenarioName(arraySize)
parallelScenarioName(arraySize - 1) = str
End Sub
Sub AddScenarioEndRow(row As Variant, ByRef arraySize As Long, ByRef parallelScenarioEnd() As Long)
ReDim Preserve parallelScenarioEnd(arraySize)
parallelScenarioEnd(arraySize - 1) = row - 1
End Sub
Sub AddNewScenarioStartRow(row As Variant, ByRef arraySize As Long, ByRef parallelScenarioStart() As Long)
ReDim Preserve parallelScenarioStart(arraySize)
parallelScenarioStart(arraySize - 1) = row
End Sub
This will work on unsorted data, but will be much faster if you sort first.
Sub AllocateData()
Dim shtRaw As Worksheet, currVal, rng As Range
Dim c As Range, rngCopy As Range, i As Long, tmp
Set shtRaw = Sheets("raw")
On Error GoTo haveError
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Set rng = shtRaw.Range(shtRaw.Range("B1"), _
shtRaw.Cells(Rows.Count, "B").End(xlUp))
currVal = "~~~~~~~~~~~~~~~" 'or any non-value
For Each c In rng.Cells
tmp = c.Value
If tmp <> currVal Then
If Not rngCopy Is Nothing Then
rngCopy.Copy Sheets(currVal).Cells(Rows.Count, _
"A").End(xlUp).Offset(1, 0)
End If
Set rngCopy = c.Offset(0, -1).Resize(1, 4)
currVal = tmp
i = 1
Else
i = i + 1
Set rngCopy = rngCopy.Resize(i, 4)
End If
Next c
If Not rng Is Nothing Then
rngCopy.Copy Sheets(currVal).Cells(Rows.Count, "A").End(xlUp).Offset(1, 0)
End If
haveError:
'must reset calculation, or it will remain on "manual"
Application.Calculation = xlCalculationAutomatic
'ScreenUpdating will auto-reset once the sub exits,
' but I think it's good practise to explicitly reset it
Application.ScreenUpdating = True
End Sub
Copy-paste is, in my expreience, the slowest thing you can do in VBA.
Try simply assigning the values of range 1 to range 2, kinda like this:
range("b1:b4").value=range("a1:a4").value
Make sure the ranges are of the same size.
In your AllocateData sub, you could use something like:
Worksheets(parallelScenarioName(intPosition)).activate
Range(cells(1,1),cells(scenariorange.rows.count,1).value=scenariorange.value
Sheets("raw").Activate
Oh, I have changed scenariorange to be a range variable, lot easier to use in my opinion. Use it like this:
Dim ScenarioRange as Range
Set ScenarioRange = Range("A" & parallelScenarioStart(intPosition) & ":" & "D" & parallelScenarioEnd(intPosition))
Hope this speeds things up. (And I hope you can understand what I'm trying to say here, I'm a bit sleepy... :) )
Also, turning off the screenupdating usually speeds up the program a lot.
application.screenupdating=false
Don't forget to turn it back on at the end of the code!
My requirements ended up changing slightly. The QA lead wanted Metadata in the raw worksheet, so I had the full list of scenarios at my disposal instead of having to look at every row in the raw data. As a result, I could save and sort the scenario list to an array, and then do a .Find(parallelScenarioName(intPosition + 1)).row to get the row of the next scenario.
Because of this change, I did not fully implement and test Tim Williams solution which would iterate through every row in the data. I have to move on for now, but will revisit and test Tim's solution for my own knowledge soon.
The finished code is below.
'This is in a module so that my subs can see it
Option Explicit
Public Const DATASOURCE_WORKSHEET As String = "raw"
'This is the macro is called. Can be considered main.
Sub AllocateImportedData()
Call SortDataSourceWorksheet
Call AllocateData
End Sub
Sub SortDataSourceWorksheet()
Dim entireRangeToSort As String
Dim colToSortUpon As String
Dim lastRow As Long
lastRow = FindLastRowOfRawData
entireRangeToSort = ConstructRangeString("A", 1, "D", lastRow)
colToSortUpon = ConstructRangeString("B", 1, "B", lastRow)
Call SortRangeByColumnAtoZ(entireRangeToSort, colToSortUpon)
End Sub
Sub SortRangeByColumnAtoZ(entireRangeToSort As String, colToSortUpon As String)
ActiveWorkbook.Worksheets(DATASOURCE_WORKSHEET).Sort.SortFields.Clear
ActiveWorkbook.Worksheets(DATASOURCE_WORKSHEET).Sort.SortFields.Add Key:=Range(colToSortUpon), _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets(DATASOURCE_WORKSHEET).Sort
.SetRange Range(entireRangeToSort)
.Header = xlGuess
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub
Sub AllocateData()
Dim scenarioRange As String 'To hold the composite range
Dim parallelScenarioName() As String 'Holds the unique scenario names
Dim parallelScenarioStart() As Long 'Holds the starting row of the scenario
Dim parallelScenarioEnd() As Long 'Holds the ending row of the scenario
Sheets(DATASOURCE_WORKSHEET).Activate
Call PopulateParallelScenarioArrays(parallelScenarioName, parallelScenarioStart, parallelScenarioEnd)
Call PerformAllocation(parallelScenarioName, parallelScenarioStart, parallelScenarioEnd)
Call FinishByActivatingDesiredWorksheet(DATASOURCE_WORKSHEET)
End Sub
Sub PerformAllocation(ByRef parallelScenarioName() As String, ByRef parallelScenarioStart() As Long, ByRef parallelScenarioEnd() As Long)
For intPosition = LBound(parallelScenarioName) To (UBound(parallelScenarioName) - 1)
scenarioRange = ConstructRangeString("A", parallelScenarioStart(intPosition), "D", parallelScenarioEnd(intPosition))
Range(scenarioRange).Select
Selection.Copy
Worksheets(parallelScenarioName(intPosition)).Activate
Range("A1").Select
ActiveSheet.Paste
Sheets(DATASOURCE_WORKSHEET).Activate
Next
End Sub
Sub PopulateParallelScenarioArrays(ByRef parallelScenarioName() As String, ByRef parallelScenarioStart() As Long, ByRef parallelScenarioEnd() As Long)
Dim numberOfScenarios As Long
numberOfScenarios = GetScenarioListFromRaw(parallelScenarioName)
ReDim parallelScenarioStart(numberOfScenarios)
ReDim parallelScenarioEnd(numberOfScenarios)
Call GetStartAndEndRows(parallelScenarioName, parallelScenarioStart, parallelScenarioEnd)
End Sub
Function GetScenarioListFromRaw(ByRef parallelScenarioName() As String) As Long
Dim numberOfScenarios As Long
Dim scenarioRange As String
Const scenarioListStartColumn As String = "F"
Const scenarioListStartRow As Long = "3"
numberOfScenarios = GetNumberOfScenarios(scenarioListStartColumn, scenarioListStartRow)
ReDim parallelScenarioName(numberOfScenarios)
'Populate parallel scenario name
For i = 0 To (numberOfScenarios - 1)
scenarioRange = scenarioListStartColumn & (scenarioListStartRow + i)
parallelScenarioName(i) = Range(scenarioRange).Text
Next
Call AtoZBubbleSort(parallelScenarioName)
GetScenarioListFromRaw = numberOfScenarios
End Function
Function GetNumberOfScenarios(scenarioListStartColumn As String, scenarioListStartRow As Long)
GetNumberOfScenarios = Range(scenarioListStartColumn & scenarioListStartRow, Range(scenarioListStartColumn & scenarioListStartRow).End(xlDown)).Rows.Count
End Function
Sub GetStartAndEndRows(ByRef parallelScenarioName() As String, ByRef parallelScenarioStart() As Long, ByRef parallelScenarioEnd() As Long)
Dim TotalRows As Long
Dim newScenarioRow As Long
'Prep the parallel array for scenario name with the first value
parallelScenarioStart(0) = 1 'First spot on the scenario start will be row 1
'Get the total amount of rows
TotalRows = Rows(Rows.Count).End(xlUp).row
For intPosition = LBound(parallelScenarioName) To (UBound(parallelScenarioName) - 1)
'Find the row of the next scenario
newScenarioRow = Worksheets(DATASOURCE_WORKSHEET).Columns(2).Find(parallelScenarioName(intPosition + 1)).row
'Next scenario row - 1 is going to be the end of the current row
parallelScenarioEnd(intPosition) = newScenarioRow - 1
'Set starting row of next scenario
parallelScenarioStart(intPosition + 1) = newScenarioRow
Next
End Sub
Sub FinishByActivatingDesiredWorksheet(desiredWorksheet As String)
Sheets(desiredWorksheet).Activate
Range("A1").Select
End Sub
Sub AtoZBubbleSort(ByRef parallelScenarioName() As String)
Dim s1 As String, s2 As String
Dim i As Long, j As Long
For i = LBound(parallelScenarioName) To UBound(parallelScenarioName)
For j = i To UBound(parallelScenarioName)
If UCase(parallelScenarioName(j)) < UCase(parallelScenarioName(i)) Then
s1 = parallelScenarioName(j)
s2 = parallelScenarioName(i)
parallelScenarioName(i) = s2
parallelScenarioName(j) = s1
End If
Next
Next
End Sub
Sub ClearWorkbookCells()
Dim anyWS As Worksheet
For Each anyWS In ThisWorkbook.Worksheets
Call ClearWorksheetCells(anyWS)
Next
End Sub
Sub ClearWorksheetCells(ws As Worksheet)
ws.Activate
' Find the last row and create range var
lastRow = FindLastRowOfRawData
ClearRange = "A1:" & "D" & lastRow
'Select the area to clear and perform clear
ActiveSheet.Range(ClearRange).Select
Selection.ClearContents
End Sub
Function FindLastRowOfRawData()
FindLastRowOfRawData = Range("A1").End(xlDown).row
End Function
Function ConstructRangeString(startCol As String, startRow As Long, endCol As String, endRow As Long) As String
ConstructRangeString = startCol & startRow & ":" & endCol & endRow
End Function
A sub calls a function that in turn doest stuff and returns an array. The probem is I need to know the size of that array in my sub. is there a quick line to find the size of that array? I know i can do it with a littel for loop bt this seems unecessary.
This is how it goes:
Sub innout(lastupdate As Long, lrcr As Long)
Dim numclosed As Long, numnew As Long
Dim lblvar As Variant
Dim tblcr As Range
Dim finishdates As Range
Dim msg As Long
Dim resp As String, ops() As Long, cps() As Long
Dim i As Long
listallsupv
'do stuff...
end sub
Function listallsupv() As String()
Dim las() As String
Dim lrs As Long
Dim i As Long, j As Long, r As Long
Dim supervsheet As Worksheet
Set supervsheet = Sheets("Superviseurs")
lrs = supervsheet.Range("A1").Offset(supervsheet.Rows.count - 1, 0).End(xlUp).Row
ReDim las(1 To lrs) As String
i = 1
For r = 2 To lrs
For j = 1 To i
If supervsheet.Range("B" & r).Value = las(j) Then
GoTo nextj
End If
Next
las(i) = supervsheet.Range("B" & r).Value
i = i + 1
nextj:
Next
ReDim Preserve las(1 To i)
End Function
Thanks!
ah I found it. I just made the array in my original sub and called another sub to populate it by reference adnn also return the length. Ya thanks Tim I hadn't even noticed that at first.
Sub innout(lastupdate As Long, lrcr As Long)
Dim i As Long
Dim las() As String
Call populate_las(las(), i)
'bla bla
End Sub
Sub populate_las(ByRef las() As String, ByRef i As Long)
Dim lrs As Long
Dim j As Long, r As Long
Dim supervsheet As Worksheet
Set supervsheet = Sheets("Superviseurs")
lrs = supervsheet.Range("A1").Offset(supervsheet.Rows.count - 1, 0).End(xlUp).Row
ReDim las(1 To lrs) As String
i = 1
For r = 2 To lrs
For j = 1 To i
If supervsheet.Range("B" & r).Value = las(j) Then
GoTo nextj
End If
Next
las(i) = supervsheet.Range("B" & r).Value
i = i + 1
nextj:
Next
ReDim Preserve las(1 To (i - 1))
End Sub
Thanks again!
how do i filter an array using another array vb6
Edit
given an array A, remove all elements in array B from array A
In that case, I'd just sort one array, then iterate through the second, deleting things from the first array if they are found. This algorithm seems to take O(n lg n) and does what you want it to do.
Assuming they are integer arrays:
Dim FilteredArray() As Integer
Dim X as Long
Dim Y as Long
Dim Z as Long
Dim bDupe as Boolean
Z = -1
For X = 0 to UBound(A)
bDupe = False
For Y = 0 to UBound(B)
If A(X) = B(Y) Then
bDupe = True
Exit For
End If
Next
If Not bDupe Then
Z = Z + 1
ReDim Preserve FilteredArray(Z)
FilteredArray(Z) = A(X)
End If
Next
Try something like this
Option Explicit
Private Sub Form_Load()
Dim vElem As Variant
For Each vElem In SubstractArray(Array("aa", "b", "test"), Array("c", "aa", "test"))
Debug.Print vElem
Next
End Sub
Private Function SubstractArray(arrSrc As Variant, arrBy As Variant) As Variant
Dim cIndex As Collection
Dim vElem As Variant
Dim vRetVal As Variant
Dim lIdx As Long
If UBound(arrSrc) < LBound(arrSrc) Then
Exit Function
End If
'--- build index collection
Set cIndex = New Collection
For Each vElem In arrBy
cIndex.Add vElem, "#" & vElem
Next
'--- allocate output array
lIdx = LBound(arrSrc)
ReDim vRetVal(lIdx To UBound(arrSrc)) As Variant
'--- iterate source and seek in index
For Each vElem In arrSrc
On Error Resume Next
IsObject cIndex("#" & vElem)
If Err.Number <> 0 Then
vRetVal(lIdx) = vElem
lIdx = lIdx + 1
End If
On Error GoTo 0
Next
'--- shrink output array
If lIdx = LBound(vRetVal) Then
vRetVal = Split(vbNullString)
Else
ReDim Preserve vRetVal(0 To lIdx - 1) As Variant
End If
SubstractArray = vRetVal
End Function
i have found the answer myself, thanks for all who contributed
Function FilterArray(ByVal Source As String, ByVal Search As String, Optional _
ByVal Keep As Boolean = True) As String
Dim i As Long
Dim SearchArray() As String
Dim iSearchLower As Long
Dim iSearchUpper As Long
If LenB(Source) <> 0 And LenB(Search) <> 0 Then
SearchArray = Split(Search, " ")
Else
FilterArray = Source
Exit Function
End If
iSearchLower = LBound(SearchArray)
iSearchUpper = UBound(SearchArray)
For i = iSearchLower To iSearchUpper
DoEvents
Source = Join(Filter(Split(Source, " "), SearchArray(i), Keep, _
vbTextCompare), " ")
Next i
FilterArray = Source
End Function