Issue counting word frequencies with VBA: same data, different numbers - arrays

I've made two different scripts in VBA to count the frequency of words contained in a CSV. Both scripts run fine, but I get different numbers for each word and I don't know why. Here are some of the steps that lead to the moment when the difference appears
Script 1:
Sub Dict_Array_1()
Dim Wb As Workbook, Wb1 As Workbook
Dim Ws As Worksheet, Ws1 As Worksheet
Dim Fd As Office.FileDialog
Dim StrFile As String
Dim i As Long, a As Long, LastR As Long
Dim Arr() As Variant
Dim Ban_() As String, T As String
Dim Ban As Object, Dict As Object
Dim Carac As Variant, w As Variant, Key As Variant
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.DisplayStatusBar = False
Application.EnableEvents = False
ActiveSheet.DisplayPageBreaks = False
Application.DisplayAlerts = False
Set Wb = ActiveWorkbook
Set Ws = Wb.ActiveSheet
'---------- CSV ---------------------------------------------------------------------------------------------------------------
Set Fd = Application.FileDialog(msoFileDialogFilePicker)
With Fd
.AllowMultiSelect = False
.Title = "Select doc"
.Filters.Clear
.Filters.Add "Doc CSV (*.csv)", "*.csv"
If .Show Then
On Error GoTo ErrOpen 'ignore this
Set Wb1 = Workbooks.Open(.SelectedItems(1), ReadOnly:=True, Local:=False)
On Error GoTo 0
Set Ws1 = Wb1.Sheets(1)
With Ws1
LastR = .Cells(.Rows.Count, "S").End(xlUp).Row
Arr = .Range(Cells(1, 19), Cells(LastR, 19)).Value2
End With
Wb1.Close 0
Set Wb1 = Nothing
Set Ws1 = Nothing
Else
Exit Sub
End If
End With
'---------------------------------------- COUNT ----------------------------------------------------------------------------------------------------
'Array with words i want to ban
Ban_ = Split("word1,word2,word3,etc", ",")
'Array with caract i want to ban
Carac = Array(".", ",", ";", ":", "!", "#", "$", "%", "&", "(", ")", "- ", "_", "--", "+", _
"=", "~", "/", "\", "{", "}", "[", "]", """", "?", "*", ">>", "»", "«")
Set Ban = CreateObject("Scripting.Dictionary") 'need late binding
Ban.CompareMode = vbTextCompare 'case insensitive
For i = 0 To UBound(Ban_)
Ban.Add Ban_(i), 1
Next i
Erase Ban_
'Dict to count words
Set Dict = CreateObject("Scripting.Dictionary")
Dict.CompareMode = vbTextCompare 'case insensitive
For a = 1 To UBound(Arr, 1)
If Not IsError(Arr(a, 1))
T = Arr(a, 1)
For i = 0 To UBound(Carac)
T = Replace(T, Carac(i), "", , , vbTextCompare)
Next i
T = Application.Trim(T)
For Each w In Split(T, " ")
If Not Ban.exists(w) Then
If Not Dict.exists(w) Then
Dict.Add w, 1
Else
Dict.Item(w) = Dict.Item(w) + 1
End If
End If
Next w
End If
Next a
Exit Sub
Erase Arr
Erase Carac
Set Ban = Nothing
Script 2 is basically the same, only difference is that I access the .CSV in another way:
Sub Dict_ADODB()
Dim Wb As Workbook, Wb1 As Workbook
Dim Ws As Worksheet, Ws1 As Worksheet
Dim Fd As Office.FileDialog
Dim StrFile As String
Dim i As Long, a As Long, LastR As Long
Dim Arr() As Variant
Dim Ban_() As String, T As String
Dim Ban As Object, Dict As Object
Dim Carac As Variant, w As Variant, Key As Variant
Dim ObjC As Object, ObjR As Object 'Object Connection / Object Recordset
Const adOpenStatic = 3
Const adLockOptimistic = 3
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.DisplayStatusBar = False
Application.EnableEvents = False
ActiveSheet.DisplayPageBreaks = False
Application.DisplayAlerts = False
Set Wb = ActiveWorkbook
Set Ws = Wb.ActiveSheet
'---------- CSV ---------------------------------------------------------------------------------------------------------------
Set Fd = Application.FileDialog(msoFileDialogFilePicker)
With Fd
.AllowMultiSelect = False
.Title = "Select doc"
.Filters.Clear
.Filters.Add "Doc CSV (*.csv)", "*.csv"
If .Show Then
'----------- ADODB ---
Set ObjC = CreateObject("ADODB.Connection")
Set ObjR = CreateObject("ADODB.RecordSet")
On Error GoTo ErrOpen
ObjC.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & .InitialFileName & ";" & _
"Extended Properties=""text;HDR=YES;FMT=Delimited;CharacterSet=65001"""
On Error GoTo 0
'I just need one column
ObjR.Open "SELECT Message FROM " & Right(.SelectedItems(1), Len(.SelectedItems(1)) - InStrRev(.SelectedItems(1), "\")) & _
" WHERE Message IS NOT NULL", _
ObjC, adOpenStatic, adLockOptimistic
Arr = ObjR.GetRows()
ObjR.Close
ObjC.Close
Set ObjR = Nothing
Set ObjC = Nothing
Else
Exit Sub
End If
End With
'---------------------------------------- COUNT ----------------------------------------------------------------------------------------------------
'Array with word I don't need
Ban_ = Split("word1,word2", ",")
Carac = Array(".", ",", ";", ":", "!", "#", "$", "%", "&", "(", ")", "- ", "_", "--", "+", _
"=", "~", "/", "\", "{", "}", "[", "]", """", "?", "*", ">>", "»", "«")
Set Ban = CreateObject("Scripting.Dictionary")
Ban.CompareMode = vbTextCompare
For i = 0 To UBound(Ban_)
Ban.Add Ban_(i), 1
Next i
Erase Ban_
Set Dict = CreateObject("Scripting.Dictionary")
Dict.CompareMode = vbTextCompare 'case insensitive
For a = 0 To UBound(Arr, 2)
If Not IsError(Arr(0, a)) Then
T = Arr(0, a)
For i = 0 To UBound(Carac)
T = Replace(T, Carac(i), "", , , vbTextCompare)
Next i
T = Application.Trim(T)
For Each w In Split(T, " ")
If Not Ban.exists(w) Then
If Not Dict.exists(w) Then
Dict.Add w, 1
Else
Dict.Item(w) = Dict.Item(w) + 1
End If
End If
Next w
End If
Next a
Erase Arr
Erase Carac
Set Ban = Nothing
Exit Sub
Here you go. When I do dict.count I do find that the total number of entries is different, which is only partly explained by the use of "WHERE Message IS NOT NULL". Any idea why would be greatly appreciated!

The best case to see what is happening is to write some log this line:
Dict.Add w, 1
E.g., if the values are up to 200, then write:
Dim cnt as long
Dict.Add w, 1
cnt = cnt + 1
Debug.Print cnt, w
If the values are above 200, then only the last 200 would be displayed on the immediate window, thus it will not help you a lot. You can build a String with the log and print the String in a Notepad exactly with the same.
Dim cnt as Long
Dim logString as String
Dict.Add w, 1
cnt = cnt + 1
logString = logString & VbCrLF & cnt, w
And at the end CreateLogFile logString:
Sub CreateLogFile(Optional strPrint As String)
Dim fs As Object
Dim obj_text As Object
Dim str_filename As String
Dim str_new_file As String
Dim str_shell As String
str_new_file = "\tests_info\"
str_filename = ThisWorkbook.Path & str_new_file
If Dir(ThisWorkbook.Path & str_new_file, vbDirectory) = vbNullString Then
MkDir ThisWorkbook.Path & str_new_file
End If
Set fs = CreateObject("Scripting.FileSystemObject")
Set obj_text = fs.CreateTextFile(str_filename & "\sometext.txt", True)
obj_text.writeline (strPrint)
obj_text.Close
str_shell = "C:\WINDOWS\notepad.exe "
str_shell = str_shell & str_filename & "\sometext.txt"
Shell str_shell
End Sub

Alright, using a Schema.ini seems to have fixed my issue. Something that is not clear in the documentation is that one should set "colX= Y Type" for each column in the CSV until the one he wants to select (at first I only set "Col19=Message" but it failed because the previous columns where not set...).
I'm sharing the relevant part of the code for anyone interested (Excel 2010 / X86 version):
Set fs = CreateObject("Scripting.FileSystemObject")
Set obj_text = fs.CreateTextFile(.InitialFileName & "\Schema.ini", True)
obj_text.write ("[" & Right(.SelectedItems(1), Len(.SelectedItems(1)) - InStrRev(.SelectedItems(1), "\")) & "]" & vbNewLine & _
"ColNameHeader=False" & vbNewLine & _
"CharacterSet=65001" & vbNewLine & _
"Format=CSVDelimited" & vbNewLine & _
"DecimalSymbol=." & vbNewLine & _
"Col1=1 Text" & vbNewLine & _
"Col2=2 Text" & vbNewLine & _
"Col3=3 Text" & vbNewLine & _
"Col4=4 Text" & vbNewLine & _
"Col5=5 Text" & vbNewLine & _
"Col6=6 Text" & vbNewLine & _
"Col7=7 Text" & vbNewLine & _
"Col8=8 Text" & vbNewLine & _
"Col9=9 Text" & vbNewLine & _
"Col10=10 Text" & vbNewLine & _
"Col11=11 Text" & vbNewLine & _
"Col12=12 Text" & vbNewLine & _
"Col13=13 Text" & vbNewLine & _
"Col14=14 Text" & vbNewLine & _
"Col15=15 Text" & vbNewLine & _
"Col16=16 Text" & vbNewLine & _
"Col17=17 Text" & vbNewLine & _
"Col18=18 Text" & vbNewLine & _
"Col19=GOODONE Memo") 'set all the previous cols until the one I need!
obj_text.Close
Set ObjC = CreateObject("ADODB.Connection")
Set ObjR = CreateObject("ADODB.RecordSet")
ObjC.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & .InitialFileName & ";" & _
"Extended Properties=""text;HDR=No;"""
ObjR.Open "SELECT GOODONE FROM " & Right(.SelectedItems(1), Len(.SelectedItems(1)) - InStrRev(.SelectedItems(1), "\")), _
ObjC, 0, 1
Arr = ObjR.GetRows()

Related

How to copy a row N number of times in the same column in Excel?

We are not able to create a formula which will copy 200 rows of a column in a same order and paste it multiple times in the same column and in the same order.
Example: columns A1:A200 have names in a particular order and we want to repeat the same order in the same column for 3000 times.
What is the way to do it without manual dragging?
Multi-Stack a Range Vertically
Sub VMultiStackTEST()
Const SourceRangeAddress As String = "A1:A200"
Const DestinationFirstCellAddress As String = "A1"
Const StackCount As Long = 3000
Dim ws As Worksheet: Set ws = ActiveSheet ' improve!
Dim srg As Range: Set srg = ws.Range(SourceRangeAddress)
Dim dfCell As Range: Set dfCell = ws.Range(DestinationFirstCellAddress)
VMultiStack srg, dfCell, StackCount
' or (instead) just e.g.:
'VMultiStack Range("A1:A200"), Range("A1"), 3000
End Sub
Sub VMultiStack( _
ByVal SourceRange As Range, _
ByVal DestinationFirstCell As Range, _
Optional ByVal StackCount As Long = 1)
Const ProcName As String = "VMultiStack"
On Error GoTo ClearError
Dim IsSuccess As Boolean
Dim sData As Variant
Dim srCount As Long
Dim cCount As Long
Dim sAddress As String
With SourceRange.Areas(1)
sAddress = .Address(0, 0)
srCount = .Rows.Count
cCount = .Columns.Count
If srCount + cCount = 2 Then
ReDim sData(1 To 1, 1 To 1): sData(1, 1) = .Value
Else
sData = .Value
End If
End With
Dim dData As Variant: ReDim dData(1 To srCount * StackCount, 1 To cCount)
Dim n As Long
Dim sr As Long
Dim dr As Long
Dim c As Long
For n = 1 To StackCount
For sr = 1 To srCount
dr = dr + 1
For c = 1 To cCount
dData(dr, c) = sData(sr, c)
Next c
Next sr
Next n
Dim dAddress As String
With DestinationFirstCell.Resize(, cCount)
With .Resize(dr)
.Value = dData
dAddress = .Address(0, 0)
End With
.Resize(.Worksheet.Rows.Count - .Row - dr + 1).Offset(dr).Clear
End With
IsSuccess = True
ProcExit:
If IsSuccess Then
MsgBox "Stacked '" & sAddress & "' " & StackCount & " times to '" _
& dAddress & "'.", _
vbInformation, ProcName
Else
If Len(sAddress) > 0 Then
MsgBox "Could not stack '" & sAddress & "' " & StackCount _
& " times. No action taken.", _
vbExclamation, ProcName
Else
MsgBox "The program failed.", vbCritical, ProcName
End If
End If
Exit Sub
ClearError:
Debug.Print "'" & ProcName & "' Run-time error '" _
& Err.Number & "':" & vbLf & " " & Err.Description
Resume ProcExit
End Sub
With Office 365, you can put this into a LET as follows:
=LET( a, A1:A200, mBy, 3000,
r, ROWS( a ),
s, r * mBy,
INDEX( a, MOD(SEQUENCE( s,,0 ),r) + 1 ) )
where a is the column of names and mBy is the multiple (3000).
If you want to simplify it:
= INDEX( A1:A200, MOD(SEQUENCE( ROWS(A1:A200) * 3000,,0 ),ROWS(A1:A200)) + 1 )

How do i get a loop so that for each cell in 4 columns (note each cells per column is a Criteria) it checks for the price in a database

I am writing a Excel file that can get a price form a database depending on 4 Criteria. I got to the point that it can find in one row the price (in the row there are first the 4 criteria and then the price)[See picture1]. but what i want is that every row can find the matching price. The code that i have now is this:
Option Explicit
Sub cmdSearch_Click()
Dim strCriteriaEquipment As String
Dim strCriteriaType As String
Dim strCriteriaMaterial As String
Dim strCriteriaSize As String
Dim strSQL As String
Dim strSourceTable As String
With Worksheets("Summary")
strCriteriaEquipment = .Range("B29").Value
strCriteriaType = .Range("C29").Value
strCriteriaMaterial = .Range("D29").Value
strCriteriaSize = .Range("E29").Value
End With
strSourceTable = "[DB$" & Replace(Worksheets("DB").Range("SourceData").Address, "$", "") & "]"
strSQL = "SELECT [Price] FROM " & strSourceTable & vbNewLine
strSQL = strSQL & "WHERE [Equipment]= """ & strCriteriaEquipment & """" & vbNewLine
strSQL = strSQL & "AND [Type]=""" & strCriteriaType & """" & vbNewLine
strSQL = strSQL & "AND [Material]=""" & strCriteriaMaterial & """" & vbNewLine
strSQL = strSQL & "AND [Size]=""" & strCriteriaSize & """;"
Call TableFetcher(strSQL)
strSQL = vbNullString
strCriteriaEquipment = vbNullString
strCriteriaType = vbNullString
strCriteriaMaterial = vbNullString
strCriteriaSize = vbNullString
strSourceTable = vbNullString
End Sub
Option Explicit
Public Const adOpenStatic = 3
Public Const adOpenKeySet = 1
Public Const adLockReadOnly = 1
Sub Fetcher(strSQL As String, Optional strDropDownName As String)
Dim rstRecordSet As Object 'ADODB.Recordset
Dim con As Object 'ADODB.Connection
Dim strWorkBookPath As String
strWorkBookPath = ThisWorkbook.FullName
Set con = CreateObject("ADODB.Connection")
Set rstRecordSet = CreateObject("ADODB.RecordSet")
con.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & strWorkBookPath & ";" & _
"Extended Properties=""Excel 8.0;HDR=Yes"";"
rstRecordSet.Open strSQL, con, adOpenStatic, adLockReadOnly
With Worksheets("Summary")
With .DropDowns(strDropDownName)
.RemoveAllItems
.List = Split(UniqueStringWithDelimiter(rstRecordSet.GetRows, "|"), "|")
.Value = 1
End With
End With
rstRecordSet.Close
con.Close
Set rstRecordSet = Nothing
Set con = Nothing
strWorkBookPath = vbNullString
End Sub
Sub TableFetcher(strSQL As String)
Dim rstRecordSet As Object 'ADODB.Recordset
Dim con As Object 'ADODB.Connection
Dim strWorkBookPath As String
strWorkBookPath = ThisWorkbook.FullName
Set con = CreateObject("ADODB.Connection")
Set rstRecordSet = CreateObject("ADODB.RecordSet")
con.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & strWorkBookPath & ";" & _
"Extended Properties=""Excel 8.0;HDR=Yes"";"
rstRecordSet.Open strSQL, con, adOpenStatic, adLockReadOnly
With Worksheets("Summary")
If Not (rstRecordSet.EOF And rstRecordSet.BOF) Then
.Range("ResultTable").Cells(5).CopyFromRecordset rstRecordSet
Else
.Range("ResultTable").Cells(5).Value = "Data Not Found!"
End If
End With
rstRecordSet.Close
con.Close
Set rstRecordSet = Nothing
Set con = Nothing
strWorkBookPath = vbNullString
End Sub
Public Function UniqueStringWithDelimiter(varArray As Variant, strDelimiter As String) As Variant
Dim varTemp() As Variant
Dim lngLoop As Long
Dim strConcat As String
ReDim Preserve varTemp(0 To 0)
varTemp(0) = varArray(0, 0)
strConcat = strConcat & varArray(0, 0)
For lngLoop = 1 To UBound(varArray, 2)
If InStr(1, strConcat, varArray(0, lngLoop), vbTextCompare) = 0 Then
strConcat = strConcat & strDelimiter & varArray(0, lngLoop)
End If
Next lngLoop
UniqueStringWithDelimiter = strConcat.
strConcat = vbNullString
Erase varTemp
End Function
How i do change the code so it does what i need it to do
What I think i'm reading is that, if four (4) criteria are met, you would then find a price. Have you used an If statement with AND modifier utilizing your four (4) criteria?
This could happen in a loop, such as:
Dim r as Long, c as Long, LR as Long
LR = Cells(Rows.Count,1).End(xlUp).Row 'Assumes column 1 is contiguous
For r = 1 to LR
c=4 'assumes you're starting with column 4
If Cells(r,c).Value="Blah" AND Cells(r,c+1).Value ="Moo" AND Cells(r,c+2).Value="Ruff" AND Cells(r,c+3).Value="Shamoo" Then
Cells(r,c+4).Copy
End If
Next r

Run-time error 3061 Too few Parameters. Expected 2

Can someone please let me know what is wrong with this code? I have checked all lines for misspellings - this isnt the issue. All tables and queries are written as they exist in the db. Any help is appreciated.
Private Sub LoadArray()
'---------------------------
'---------------------------
'This procedure loads text into the 3rd column of the array
'---------------------------
'---------------------------
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim rsFiltered As DAO.Recordset
Dim strSQL As String
Dim i As Integer
strSQL = "SELECT tblProperties.Name, tbl1OpportuniyType.Type, qryPropertiesALLTypesALLTbls.TotalUnits, " _
& "qryPropertiesALLTypesALLTbls.EventStartTimeEachDay, qryPropertiesALLTypesALLTbls.EventEndTimeEachDay, " _
& "qryPropertiesALLTypesALLTbls.EventStartDate, qryPropertiesALLTypesALLTbls.EventStopDate, " _
& "qryPropertiesALLTypesALLTbls.TechOpsGroup, qryPropertiesALLTypesALLTbls.TechOpsResource " _
& "FROM tbl1OpportuniyType RIGHT JOIN (qryPropertiesALLTypesALLTbls INNER JOIN tblProperties ON qryPropertiesALLTypesALLTbls.[PropertyComplex_ID] = tblProperties.[PropertyComplex_ID]) ON tbl1OpportuniyType.[OpportunityType_ID] = tblProperties.OpportunityType " _
& "WHERE (((qryPropertiesALLTypesALLTbls.EventStartDate) Is Not Null));"
'Debug.Print strSQL
Set db = CurrentDb
Set rs = db.OpenRecordset(strSQL)
'This line ensures that the recordset is populated
If Not rs.BOF And Not rs.EOF Then
'Loops through the Array using dates for the filter
For i = LBound(myArray) To UBound(myArray)
If myArray(i, 1) Then
'Filters recordset with array dates
rs.Filter = "[EventStartDate]= " & myArray(i, 0)
'Open up new recordset based on filter
Set rsFiltered = rs.OpenRecordset
'Loop through new recordset
Do While (Not rsFiltered.EOF)
'Adds text to the 3rd column of the array
myArray(i, 2) = myArray(i, 2) & vbNewLine _
& rsFiltered!Type & " - " & vbNewLine _
& rsFiltered!Name & " " _
& rsFiltered!EventStartDate & " - " _
& rsFiltered!EventStopDate & " " _
& rsFiltered!EventStartTimeEachDay & " - " _
& rsFiltered!TechOpsGroup & " " _
& rsFiltered!TechOpsResource & " " _
& vbNewLine
rsFiltered.MoveNext
Loop
End If
Next i
End If
rsFiltered.Close
rs.Close
'Sets objects to nothing
Set rsFiltered = Nothing
Set rs = Nothing
Set db = Nothing
End Sub
It isn't clear where myArray comes from, but the filter needs an adjustment to convert the date value to a string expression:
rs.Filter = "[EventStartDate] = #" & Format(myArray(i, 0), "yyyy\/mm\/dd") & "#"

Can't pass string into array function : subscript out of range

I'm trying to imitate copying multiple sheets to a new workbook and this is fine if I literally use the sheet names in the array function.
However if I try to pass a string variable into the array I get a subscript out of range error.
The line of concern is:
Wb.Sheets(Array(SheetsArray)).Copy After:=RegionWb.Sheets(RegionWb.Sheets.count)
Please see my code below :
Sub CreateFiles()
Application.ScreenUpdating = False
Dim LastRow As Long
Dim WKC As String: WKC = Replace(DateValue(DateAdd("ww", -1, Now() - (Weekday(Now(), vbMonday) - 1))), "/", ".")
Dim FilePath As String: FilePath = "Z:\MI\Krishn\Retail"
Dim BuyerLastRow As Long
Dim Wb As Workbook: Set Wb = ActiveWorkbook
Dim RegionWb As Workbook
Dim RegionCount As Integer
Dim RegionCounter As Integer
Dim SheetsArray As String
With BuyerList
LastRow = .Range("G1048576").End(xlUp).Row
BuyerLastRow = .Range("A1048576").End(xlUp).Row
'Create WKC Dir
If Dir(FilePath & "\" & WKC, vbDirectory) = "" Then
MkDir FilePath & "\" & WKC
End If
'Create Create Files
If CountFiles(FilePath & "\" & WKC) = 0 Then
For i = 2 To LastRow
RegionCounter = 0
SheetsArray = ""
' Set RegionWb = Workbooks.Add
' 'wb.SaveAs FilePath & "\" & WKC & "\" & .Cells(i, 7).Value
' RegionWb.SaveAs FilePath & "\" & WKC & "\" & "WKC " & WKC & " - " & .Cells(i, 7).Value & ".xlsb", 50
For j = 2 To BuyerLastRow
RegionCount = Application.WorksheetFunction.CountIf(.Range("C:C"), .Cells(i, 7).Value)
If .Cells(i, 7).Value = .Cells(j, 3).Value Then
SheetsArray = SheetsArray & """" & .Cells(j, 2).Value & ""","
RegionCounter = RegionCounter + 1
If RegionCounter = RegionCount Then
Debug.Print Left(SheetsArray, Len(SheetsArray) - 1)
Set RegionWb = Workbooks.Add
RegionWb.SaveAs FilePath & "\" & WKC & "\" & "WKC " & WKC & " - " & .Cells(i, 7).Value & ".xlsb", 50
'Wb.Sheets(Array(Left(SheetsArray, Len(SheetsArray) - 1))).Copy After:=RegionWb.Sheets(RegionWb.Sheets.count)
SheetsArray = Left(SheetsArray, Len(SheetsArray) - 1)
Wb.Sheets(Array(SheetsArray)).Copy After:=RegionWb.Sheets(RegionWb.Sheets.count)
'Wb.Sheets(Array()).Copy After:=RegionWb.Sheets(RegionWb.Sheets.count)
RegionWb.Save
RegionWb.Close
Exit For
End If
' Wb.Sheets(Wb.Sheets("Buyer list").Range(Cells(j, 2).Address).Value).Copy After:=RegionWb.Sheets(RegionWb.Sheets.count)
End If
Next j
'
'
Next i
End If
End With
Application.ScreenUpdating = True
End Sub
You can split the string into an Array like this:
Wb.Sheets(Split(SheetsArray, ",")).Copy After:=RegionWb.Sheets(RegionWb.Sheets.Count)
As GSerg pointed out: You'll need to remove the quotes around the Worksheet names.
SheetsArray = SheetsArray & .Cells(j, 2).Value & ","
The backslash would be a safer delimiter that using a comma because Worksheet names can include a comma but not a backslash.
SheetsArray = SheetsArray & .Cells(j, 2).Value & "/"
Wb.Sheets(Split(SheetsArray, "/")).Copy After:=RegionWb.Sheets(RegionWb.Sheets.Count)

Using Checkboxes in Dialog Sheet to Specify Sheets to Perform Actions

I'm currently using the following code to reset an event/inventory/sales workbook. However, I was hoping to find a way to have the user select (via dialog sheet or userform with checkboxes) which sheets need to be reset. As it is right now, when the "Create New Event" button is clicked, every sheet in the sNames array is reset, but I would like for a dialog sheet or userform to popup which would allow the user to choose which sheets would be reset (aka... which ones that array would contain). So the sheets being reset would not be fixed and/or could be different each time the "Create new event" macro is run. In other words, the remaining code would stay the same, only the sheets included in the sNames array would change.
The full code that I have right now is as follows (Please note that this currently works, but the sheets being reset are fixed and/or are always the same)
Option Explicit
Sub Create_NewEvent()
Const DBLSPACE As String = vbNewLine & vbNewLine
Const BESTNFL As String = DBLSPACE & vbNewLine & _
"The Baltimore Ravens Rule!" & _
"The Forty-Winers Do NOT"
Const openMSG As String = "After pressing OK button this " & _
"will take some time." & DBLSPACE & "Amount of time " & _
"depends on whether or not the Ravens have a winning record," & _
"and whether or not..." & DBLSPACE & _
"Just be patient! Root for the Ravens and...!" & BESTNFL
Dim w As Long, I As Long, x As Long, sNames As Variant, invNames As Variant, colm As Range, tbl As Range, col1 As Range, invRng As Range
Dim wb As Workbook, ws As Worksheet, fbDate As Variant, fbEvent As Variant
Set wb = ThisWorkbook
'************************************IF YOU ADD A NEW STAND SHEET, PLEASE ADD THE SHEET NAME THIS ARRAY*********************************************************
sNames = Array(Sheet1, Sheet3, Sheet5, Sheet7, Sheet9, Sheet13, _
Sheet17, Sheet21, Sheet23, Sheet27, Sheet31, Sheet35, _
Sheet39, Sheet43, Sheet47, Sheet54, Sheet56, _
Sheet58, Sheet60, Sheet61, Sheet62, Sheet63, Sheet64, _
Sheet65, Sheet82, Sheet83, Sheet84, Sheet85, Sheet90, _
Sheet91, Sheet93, Sheet94)
'***************************************************************************************************************************************************************
'*************************IF YOU ADD A NEW NPO INVOICE, PLEASE ADD THE SHEET NAME & NUMBER IN THIS ARRAY********************************************************
invNames = Array(Sheet2, Sheet4, Sheet6, Sheet8, Sheet11, Sheet15, Sheet19, Sheet25, Sheet29, Sheet33, Sheet37, _
Sheet41, Sheet45, Sheet52, Sheet53, Sheet55, Sheet66, Sheet87)
'***************************************************************************************************************************************************************
If MsgBox("Are you sure that you want to create a new event?", vbYesNo, "Confirm") = vbYes Then
MsgBox openMSG
Application.DisplayAlerts = False
Application.ScreenUpdating = False
For w = LBound(sNames) To UBound(sNames)
With sNames(w)
Debug.Print .Name
.Range("D7:D38") = .Range("M7:M38").Value
Set tbl = .Range("B6:P38"): Set colm = .Range("M4")
ActiveWorkbook.Names.Add Name:="sTable", RefersTo:=tbl
ActiveWorkbook.Names.Add Name:="col", RefersTo:=colm
.Range("E7").Formula = "=IFERROR(IF(VLOOKUP(B7,sTable,3,FALSE)>=VLOOKUP(B7,parTable,col,FALSE),0,ROUND(SUM((VLOOKUP(B7,parTable,col,FALSE)-VLOOKUP(B7,sTable,3,FALSE))/VLOOKUP(B7,parTable,4,FALSE)),0)*VLOOKUP(B7,parTable,4,FALSE)),0)"
.Range("E7").Copy
.Range("E8:E38").PasteSpecial Paste:=xlPasteFormulas, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
.Range("E7:E38").Copy
.Range("E7:E38").PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
.Range("G7:M38,P43:P45").ClearContents
ActiveWorkbook.Names("sTable").Delete
ActiveWorkbook.Names("col").Delete
Set tbl = Nothing: Set col1 = Nothing
End With
Next w
For I = LBound(invNames) To UBound(invNames)
With invNames(I)
Debug.Print .Name
Set invRng = .Range("B56:I56")
.Range("E55").Value = 0
For x = 1 To invRng.Cells.Count
invRng.Cells(x) = ""
Next x
Set invRng = Nothing
End With
Next I
fbDate = InputBox("Please enter the new event date in the format of 2/3/2013. This will be inserted onto the standsheets. And by the way... 2/3/2013 happens to be a past superbowl. Can you guess which one?")
fbEvent = InputBox("Please Enter the new event name. This will be inserted into the cell provided for Event Name")
Sheet49.Range("B3").Value = fbDate
Sheet49.Range("B4").Value = fbEvent
Application.DisplayAlerts = True
Application.ScreenUpdating = True
MsgBox "Your new event has been created...
End If
End Sub
Nevermind everyone.... Through a few hours of trial & error, I was able to get the following code to work perfectly... Not sure if I did this correctly (syntax, best practices, etc...), but it is definitely working exactly how I wanted it to...
Option Explicit
Sub Create_NewEvent()
Const DBLSPACE As String = vbNewLine & vbNewLine
Const BESTNFL As String = DBLSPACE & vbNewLine & _
"The Baltimore Ravens Rule!" & _
"The Forty-Winers Do NOT"
Const openMSG As String = "After pressing OK button this " & _
"will take some time." & DBLSPACE & "Amount of time " & _
"depends on whether or not the Ravens have a winning record," & _
"and whether or not..." & DBLSPACE & _
"Just be patient! Root for the Ravens and...!" & BESTNFL
Dim tPos As Integer, cb As CheckBox, SheetCount As Integer, sDlg As DialogSheet
Dim w As Long, I As Long, y As Variant, x As Long, z As Long, sNames As Variant, invNames As Variant, colm As Range, tbl As Range, col1 As Range, invRng As Range
Dim wb As Workbook, ws As Worksheet, fbDate As Variant, fbEvent As Variant
Set wb = ThisWorkbook
'************************************IF YOU ADD A NEW STAND SHEET, PLEASE ADD THE SHEET NAME THIS ARRAY*********************************************************
sNames = Array(Sheet1, Sheet3, Sheet5, Sheet7, Sheet9, Sheet13, _
Sheet17, Sheet21, Sheet23, Sheet27, Sheet31, Sheet35, _
Sheet39, Sheet43, Sheet47, Sheet54, Sheet56, _
Sheet58, Sheet60, Sheet61, Sheet62, Sheet63, Sheet64, _
Sheet65, Sheet82, Sheet83, Sheet84, Sheet85, Sheet90, _
Sheet91, Sheet93, Sheet94)
'***************************************************************************************************************************************************************
'*************************IF YOU ADD A NEW NPO INVOICE, PLEASE ADD THE SHEET NAME & NUMBER IN THIS ARRAY********************************************************
invNames = Array(Sheet2, Sheet4, Sheet6, Sheet8, Sheet11, Sheet15, Sheet19, Sheet25, Sheet29, Sheet33, Sheet37, _
Sheet41, Sheet45, Sheet52, Sheet53, Sheet55, Sheet66, Sheet87)
'***************************************************************************************************************************************************************
If MsgBox("Are you sure that you want to create a new event?", vbYesNo, "Confirm") = vbYes Then
MsgBox openMSG
Application.DisplayAlerts = False
Application.ScreenUpdating = False
Set sDlg = ActiveWorkbook.DialogSheets.Add
SheetCount = 0
tPos = 40
For z = LBound(sNames) To UBound(sNames)
Set ws = sNames(z)
If Application.CountA(ws.Cells) <> 0 Then
SheetCount = SheetCount + 1
sDlg.CheckBoxes.Add 78, tPos, 150, 16.5
sDlg.CheckBoxes(SheetCount).Text = _
ws.Name
tPos = tPos + 13
End If
Set ws = Nothing
Next z
sDlg.Buttons.Left = 240
With sDlg.DialogFrame
.Height = Application.Max _
(68, sDlg.DialogFrame.Top + tPos - 34)
.Width = 230
.Caption = "Select Stands to Open"
End With
sDlg.Buttons("Button 2").BringToFront
sDlg.Buttons("Button 3").BringToFront
If SheetCount <> 0 Then
If sDlg.Show Then
For Each cb In sDlg.CheckBoxes
If cb.Value = xlOn Then
y = cb.Caption
With Sheets(y)
Debug.Print .Name
.Range("D7:D38") = .Range("M7:M38").Value
Set tbl = .Range("B6:P38"): Set colm = .Range("M4")
wb.Names.Add Name:="sTable", RefersTo:=tbl
wb.Names.Add Name:="col", RefersTo:=colm
.Range("E7").Formula = "=IFERROR(IF(VLOOKUP(B7,sTable,3,FALSE)>=VLOOKUP(B7,parTable,col,FALSE),0,ROUND(SUM((VLOOKUP(B7,parTable,col,FALSE)-VLOOKUP(B7,sTable,3,FALSE))/VLOOKUP(B7,parTable,4,FALSE)),0)*VLOOKUP(B7,parTable,4,FALSE)),0)"
.Range("E7").Copy
.Range("E8:E38").PasteSpecial Paste:=xlPasteFormulas, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
.Range("E7:E38").Copy
.Range("E7:E38").PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
.Range("G7:M38,P43:P45").ClearContents
wb.Names("sTable").Delete
wb.Names("col").Delete
Set tbl = Nothing: Set col1 = Nothing
End With
End If
Next cb
End If
Else
MsgBox "All worksheets are empty."
End If
sDlg.Delete
For I = LBound(invNames) To UBound(invNames)
With invNames(I)
Debug.Print .Name
Set invRng = .Range("B56:I56")
.Range("E55").Value = 0
For x = 1 To invRng.Cells.Count
invRng.Cells(x) = ""
Next x
Set invRng = Nothing
End With
Next I
fbDate = InputBox("Please enter the new event date in the format of 2/3/2013. This will be inserted onto the standsheets. And by the way... 2/3/2013 happens to be a past superbowl. Can you guess which one?")
fbEvent = InputBox("Please Enter the new event name. This will be inserted into the cell provided for Event Name")
Sheet49.Range("B3").Value = fbDate
Sheet49.Range("B4").Value = fbEvent
Application.DisplayAlerts = True
Application.ScreenUpdating = True
MsgBox "Your new event has been created... Don't mess anything up today Mark! The Baltimore Ravens rule!!"
End If
End Sub

Resources