VBA put data from file to Excel Sheets - file

I got file.txt structure like this:
"FIRST"
a1 b1 c1 d1
a2 b2 c2 c2
"SECOND"
e1 f1
e2 f2
"THIRD"
g1 h1
I got three sheets in my Excel file: "first", "second" and "third". How to populate this data into three sheets by VBA code?

I still think that reading a text file line per line is the best way to go.
You can load the entire file into an array and write conditions later.
Sub Read_text_File()
Dim oFSO As New FileSystemObject
Dim oFS
Dim sText as String
Dim vArray
Dim lCnt as Long
Set oFS = oFSO.OpenTextFile("c:\textfile.TXT")
Do Until oFS.AtEndOfStream
lCnt = lCnt + 1
sText = oFS.ReadLine
vArray(lCnt) = sText
Loop
End Sub
Then look through the array and do your stuff.
Or you could load the data in three separate arrays immediately, representing the three sheets.
This is entirely up to you.
Let me know if this was helpful.

Start recording a macro and open the txt file delimited by space. press ctrl + f and find First, Second and Third in three steps. copy your required range from the active workbook to your required workbook in respective sheets.
this will give you a recorded macro which you can restructure to make an automated code. Maybe i can post some code later. you will have to add lines of vba to read the line numbers of the cells used to find secon and third so that you know what range you have to copy.
1 question, number of columns in your file is as shown????
here is a code.
Sub Macro1()
Dim startRow As Integer
Dim endRow As Integer
Dim wb As Workbook
Workbooks.OpenText Filename:="D:\file.txt", Origin:=437, startRow:=1, _
DataType:=xlDelimited, TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter _
:=True, Tab:=True, Semicolon:=False, Comma:=False, Space:=True, Other _
:=False, FieldInfo:=Array(Array(1, 1), Array(2, 1), Array(3, 1), Array(4, 1)), _
TrailingMinusNumbers:=True
Set wb = ActiveWorkbook
Cells.Find(What:="FIRST", After:=ActiveCell, LookIn:=xlFormulas, LookAt _
:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, SearchFormat:=False).Activate
startRow = ActiveCell.Row + 1
Cells.Find(What:="SECOND", After:=ActiveCell, LookIn:=xlFormulas, LookAt _
:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, SearchFormat:=False).Activate
endRow = ActiveCell.Row - 1
Range("A" & startRow & ":D" & endRow).Copy
ThisWorkbook.Activate
Sheets("Sheet1").Select
Range("A1").Select
ActiveSheet.Paste
startRow = endRow + 2
wb.Activate
Cells.Find(What:="THIRD", After:=ActiveCell, LookIn:=xlFormulas, LookAt _
:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, SearchFormat:=False).Activate
endRow = ActiveCell.Row - 1
Range("A" & startRow & ":D" & endRow).Copy
ThisWorkbook.Activate
Sheets("Sheet2").Select
Range("A1").Select
ActiveSheet.Paste
wb.Activate
startRow = endRow + 2
endRow = Range("A" & Rows.Count).End(xlUp).Row
Range("A" & startRow & ":D" & endRow).Copy
ThisWorkbook.Activate
Sheets("Sheet3").Select
Range("A1").Select
ActiveSheet.Paste
wb.Close (False)
End Sub

Related

Vlookup Col_Index_Number by Header based on Array iteration?

I am running into an issue with my current code - I am hoping someone can assist:
Issue: I am trying to do a Vlookup from Workbook "ABC". The issue is, I am trying to change the VLOOKUP Col_Index_Number based on a header on workbook ABC...
So for example: For MyArray "Food" I am looking to Vlookup Column_Index_Num for "Food-Mexican" Column on workbook ABC, For MyArray Appetizers, I am looking to Vlookup Column_Index-Num for "Appetizers-American"...
Additionally, the columns will not always be in the same place for each report so it has to be based on the row 1 header of ABC workbook.
Also, sometimes the Array iteration might be skipped, if say for example, "Non-AlcoholicDrinks" is not found.
Sub WIP()
Dim wb As Workbook
Dim wsMain As Worksheet
Dim wsLookup As Worksheet
Dim rng As Range
Dim rng2 As Range
Dim rFind1 As Range
Dim rFind2 As Range
Dim rFind3 As Range
Dim MyArray As Variant
Dim LookupHeaders As Variant
Dim LookupHeaders2 As Variant
Dim LR As Long
Dim i As Long
Dim PriceCol As Long
Dim pricecol2 As Long
Dim LastColumn As Long
Dim LastColumn2 As Long
Dim LastColumn3 As Long
Dim LastColumn4 As Long
Dim IndexCol As Long
'Unformatted Price Row
Sheets("Consolidate List").Select
LR = Range("A" & Rows.Count).End(xlUp).Row
Columns("H:H").Select
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
Columns("J:N").Delete
Columns("J:J").Select
ActiveWindow.FreezePanes = True
Range("H2").Select
ActiveCell.FormulaR1C1 = "New Price"
ActiveCell.Interior.ColorIndex = 22
Range("H3:H" & LR).Formula = "=VLOOKUP(RC[-7],'Connect Report'!C[-7]:C[-6],2,FALSE)"
ActiveCell.EntireColumn.Resize(Rows.Count - 2).Offset(2).Select
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Range("I2").Select
ActiveCell.FormulaR1C1 = "Difference"
ActiveCell.Interior.ColorIndex = 22
Range("I3:I" & LR).Formula = "=IF(OR(OR(RC[-2]="""",RC[-1]="""",RC[-1]=""x"",)),"""",RC[-1]-RC[-2])"
ActiveCell.EntireColumn.Resize(Rows.Count - 2).Offset(2).Select
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Set wb = ActiveWorkbook
Sheets("Consolidate List").Select
Set wsMain = wb.ActiveSheet
Set wsLookup = wb.Sheets("Connect Report") '<-- Change to correct sheet name for the Lookup sheet
LR = wsMain.Cells(wsMain.Rows.Count, "A").End(xlUp).Row
MyArray = Array("US", "SPAIN", "California")
LookupHeaders = Array("TTIER", "Time333", "Round6")
LookupHeaders2 = Array("TELLER5", "Fly7", "Mine4")
For i = LBound(MyArray) To UBound(MyArray)
With wsMain.Rows(1)
Set rFind1 = .Find(What:=MyArray(i), LookAt:=xlWhole, MatchCase:=False, SearchFormat:=False)
If Not rFind1 Is Nothing Then
Set rng = rFind1.Offset(1).Resize(, 8)
PriceCol = Application.Match("New Opposed Price", rng, 0)
LastColumn = rFind1.Column + PriceCol
If wsMain.Cells(rng.Row, LastColumn) <> "New Opposed Price" Then
wsMain.Columns(LastColumn).Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
wsMain.Cells(rng.Row, LastColumn).Value = "New Opposed Price"
wsMain.Cells(rng.Row, LastColumn).Interior.ColorIndex = 22
LastColumn2 = LastColumn + 1
wsMain.Columns(LastColumn2).Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
wsMain.Cells(rng.Row, LastColumn2).Value = "Difference"
wsMain.Cells(rng.Row, LastColumn2).Interior.ColorIndex = 22
Set rFind2 = wsLookup.Rows(1).Find(LookupHeaders(i), wsLookup.Range("A1"), xlValues, xlWhole)
If Not rFind2 Is Nothing Then
IndexCol = rFind2.Column
wsMain.Cells(rng.Row + 1, LastColumn).Resize(LR - 2).Formula = "=VLOOKUP(A" & rng.Row + 1 & ",'Connect Report'!$A:$AL," & IndexCol & ",FALSE)"
wsMain.Cells(rng.Row + 1, LastColumn2).Resize(LR - 2).Formula = "=IF(OR(OR(RC[-2]="""",RC[-1]="""",RC[-1]=""x"",)),"""",RC[-1]-RC[-2])"
Else
MsgBox "Excel could not find " & LookupHeaders(i) & " in the lookup table."
End If
Set rng2 = rFind1.Offset(1).Resize(, 8)
pricecol2 = Application.Match("New Muted Price", rng, 0)
LastColumn3 = rFind1.Column + pricecol2
If wsMain.Cells(rng.Row, LastColumn3) <> "New Muted Price" Then
wsMain.Columns(LastColumn3).Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
wsMain.Cells(rng2.Row, LastColumn3).Value = "New Muted Price"
wsMain.Cells(rng2.Row, LastColumn3).Interior.ColorIndex = 22
LastColumn4 = LastColumn3 + 1
wsMain.Columns(LastColumn4).Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
wsMain.Cells(rng2.Row, LastColumn4).Value = "Difference"
wsMain.Cells(rng2.Row, LastColumn4).Interior.ColorIndex = 22
End If
Set rFind3 = wsLookup.Rows(1).Find(LookupHeaders2(i), wsLookup.Range("A1"), xlValues, xlWhole)
If Not rFind3 Is Nothing Then
IndexCol = rFind3.Column
wsMain.Cells(rng2.Row + 1, LastColumn3).Resize(LR - 2).Formula = "=VLOOKUP(A" & rng2.Row + 1 & ",'Connect Report'!$A:$AL," & IndexCol & ",FALSE)"
wsMain.Cells(rng2.Row + 1, LastColumn4).Resize(LR - 2).Formula = "=IF(OR(OR(RC[-2]="""",RC[-1]="""",RC[-1]=""x"",)),"""",RC[-1]-RC[-2])"
Else
MsgBox "Excel could not find " & LookupHeaders2(i) & " in the lookup table."
End If
End If
End If
End With
Next i
End Sub
Can anyone help with this? I am completely lost on how to resolve this issue. Also, I am hoping that I described the issue clearly... it is quite confusing.
I believe something like this should work for you. Give it a try and let me know.
Sub tgr()
Dim wb As Workbook
Dim wsMain As Worksheet
Dim wsLookup As Worksheet
Dim rng As Range
Dim rFind1 As Range
Dim rFind2 As Range
Dim MyArray As Variant
Dim LookupHeaders As Variant
Dim LR As Long
Dim i As Long
Dim PriceCol As Long
Dim LastColumn As Long
Set wb = ActiveWorkbook
Set wsMain = wb.ActiveSheet
Set wsLookup = wb.Sheets("ABC") '<-- Change to correct sheet name for the Lookup sheet
LR = wsMain.Cells(wsMain.Rows.Count, "A").End(xlUp).Row
MyArray = Array("TEST", "Food", "Non-AlcoholicDrinks", "Appetizers", "Alcoholic Drinks")
LookupHeaders = Array("TestHeader", "FoodHeader", "Non-AlcoholicDrinksHeader", "AppetizersHeader", "Alcoholic DrinksHeader")
For i = LBound(MyArray) To UBound(MyArray)
Set rFind1 = wsMain.Rows(1).Find(What:=MyArray(i), LookAt:=xlWhole, MatchCase:=False, SearchFormat:=False)
If Not rFind1 Is Nothing Then
Set rng = rFind1.Offset(1).Resize(, 8)
PriceCol = Application.Match("Price", rng, 0)
LastColumn = rFind1.Column + PriceCol
If wsMain.Cells(rng.Row, LastColumn) <> "Difference" Then
wsMain.Columns(LastColumn).Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
wsMain.Cells(rng.Row, LastColumn).Value = "Difference"
wsMain.Cells(rng.Row, LastColumn).Interior.ColorIndex = 22
End If
Set rFind2 = wsLookup.Rows(1).Find(LookupHeaders(i), wsLookup.Range("A1"), xlValues, xlPart)
If Not rFind2 Is Nothing Then
With wsMain.Cells(rng.Row + 1, LastColumn).Resize(LR - 2)
.Formula = "=VLOOKUP(A" & rng.Row + 1 & "," & wsLookup.Range("A:AL").Address(External:=True) & "," & rFind2.Column & ",FALSE)"
.Value = .Value 'Convert to values
End With
End If
End If
Next i
End Sub
This is a User Defined Function I've wrote to find the range of based on column header, it uses .find method to find the target cells. Works well if you column titles are are the top of your worksheet.
I hope this solves your problem, you could just findout the target column, by using .column on the range returned.
'define a range by looking for a specific text title, and return all the cells to the lastrow of the sheet as a range
Private Function defineColRange(ByVal targetWorkSheet As Worksheet, ByVal targetValue As String, _
Optional ByVal visibleOnly As Boolean, Optional ByVal rtnNoTitle As Boolean, _
Optional ByVal searchByColumn, Optional ByVal searchBackwards) As Range
Dim targetlastRow As Long
Dim targetlastCol As Long
Dim returnRange As Range
Dim findTarget As Range
'default visible only mode off
If IsMissing(visibleOnly) Then
visibleOnly = False
End If
If IsMissing(rtnNoTitle) Then 'Don't return title cell in the range returned
rtnNoTitle = False
End If
If IsMissing(searchByColumn) Then 'Search vertically by column, instead of by rows
searchByColumn = False
End If
If IsMissing(searchBackwards) Then 'Search backwards by rows
searchBackwards = False
End If
'test if targetWorkSheet is not empty
If targetWorkSheet Is Nothing Then
MsgBox ("Worksheet pass failed!"), vbExclamation
Exit Function
End If
targetWorkSheet.Activate
targetlastRow = targetWorkSheet.UsedRange.Find(What:="*", _
after:=Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
Searchorder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
targetlastCol = targetWorkSheet.UsedRange.Find(What:="*", _
after:=Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
Searchorder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Column
'find the range
If searchByColumn = True Then
Set findTarget = targetWorkSheet.UsedRange.Find(What:=targetValue, after:=Cells(1, 1), _
LookIn:=xlFormulas, Lookat:=xlPart, Searchorder:=xlByColumns, _
SearchDirection:=xlNext, MatchCase:=False)
ElseIf searchBackwards = True Then
Set findTarget = targetWorkSheet.UsedRange.Find(What:=targetValue, after:=Cells(1, targetlastCol), _
LookIn:=xlFormulas, Lookat:=xlPart, Searchorder:=xlByRows, _
SearchDirection:=xlPrevious, MatchCase:=False)
Else
Set findTarget = targetWorkSheet.UsedRange.Find(What:=targetValue, after:=Cells(1, 1), _
LookIn:=xlFormulas, Lookat:=xlPart, Searchorder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False)
End If
If findTarget Is Nothing Then
Debug.Print ("Did not find columne title """ & targetValue & ""), vbExclamation
Exit Function
Else
Dim tRow, tCol As Long
tRow = findTarget.Row
tCol = findTarget.Column
On Error Resume Next
If visibleOnly = False Then
If rtnNoTitle = False Then
Set returnRange = targetWorkSheet.Range(Cells(tRow, tCol), Cells(targetlastRow, tCol))
Set defineColRange = returnRange
Else
Set returnRange = targetWorkSheet.Range(Cells(tRow + 1, tCol), Cells(targetlastRow, tCol))
Set defineColRange = returnRange
End If
Else
If rtnNoTitle = False Then
Set returnRange = targetWorkSheet.Range(Cells(tRow, tCol), Cells(targetlastRow, tCol)).SpecialCells(xlCellTypeVisible)
Set defineColRange = returnRange
Else
Set returnRange = targetWorkSheet.Range(Cells(tRow + 1, tCol), Cells(targetlastRow, tCol)).SpecialCells(xlCellTypeVisible)
Set defineColRange = returnRange
End If
End If
If Err <> 0 Then
Debug.Print "Worksheet: " & targetWorkSheet.Name & " Column Name: " & targetValue
End If
On Error GoTo 0
Err.Clear
End If
End Function

Evaluate next value in array, if condition becomes false in macro

There are 3 values in array. Out of those, 1 value is not there in the column for which I'm filtering the data ("matang"). I want to know how should i make it skip if there is no result for that keyword. That means after filtering using that keyword, no results are displayed. I want to skip that keyword and move onto next element of array. I have tried On Error Resume Next. So any other option?
Dim Ar() As Variant
Ar() = Array("jumpsuit", "matang", "bikini")
Dim i As Variant
For Each i In Ar
Sheets("tops").Select
ActiveSheet.Range("B1").Select
Selection.AutoFilter
ActiveSheet.Range("$A$1:$D$1335").AutoFilter Field:=2, Criteria1:="*" & i & "*", Operator:=xlAnd
ActiveCell.Offset(0, 1).Range("A1").Select
Sheets("Sheet1").Select
Cells.Find(What:=i, After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate
ActiveCell.Range("A1").Select
Selection.Copy
Selection.End(xlUp).Select
Sheets("tops").Select
Do
ActiveCell.Offset(1, 0).Select
Loop While ActiveCell.EntireRow.Hidden = True
ActiveSheet.Paste
Try wrapping everything after your Autofilter in a test for no results:
If ActiveSheet.AutoFilter.Range.Columns(2).SpecialCells(xlCellTypeVisible).Count - 1 > 0 Then
ie:
Dim Ar() As Variant
Ar() = Array("jumpsuit", "matang", "bikini")
Dim i As Variant
For Each i In Ar
Sheets("tops").Select
ActiveSheet.Range("B1").Select
Selection.AutoFilter
ActiveSheet.Range("$A$1:$D$1335").AutoFilter Field:=2, Criteria1:="*" & i & "*", Operator:=xlAnd
If ActiveSheet.AutoFilter.Range.Columns(2).SpecialCells(xlCellTypeVisible).Count - 1 > 0 Then
ActiveCell.Offset(0, 1).Range("A1").Select
Sheets("Sheet1").Select
Cells.Find(What:=i, After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate
ActiveCell.Range("A1").Select
Selection.Copy
Selection.End(xlUp).Select
Sheets("tops").Select
Do
ActiveCell.Offset(1, 0).Select
Loop While ActiveCell.EntireRow.Hidden = True
ActiveSheet.Paste
End If
Next i
You could just add a CountIf bit of logic in there to test if the i'th element of the array exists in the range? And then jump past the section of code that makes changes if it doesnt exist (ie = 0)? In my example, i've used the term 'skip'. So like this....
Dim Ar() As Variant
Ar() = Array("jumpsuit", "matang", "bikini")
Dim i As Variant
For Each i In Ar
Sheets("tops").Select
ActiveSheet.Range("B1").Select
If Application.WorksheetFunction.CountIf(ActiveSheet.Range("$A$1:$D$1335"), i) = 0 Then
GoTo Skip
End If
Selection.AutoFilter
ActiveSheet.Range("$A$1:$D$1335").AutoFilter Field:=2, Criteria1:="*" & i & "*", Operator:=xlAnd
ActiveCell.Offset(0, 1).Range("A1").Select
Sheets("Sheet1").Select
Cells.Find(What:=i, After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate
ActiveCell.Range("A1").Select
Selection.Copy
Selection.End(xlUp).Select
Sheets("tops").Select
Do
ActiveCell.Offset(1, 0).Select
Loop While ActiveCell.EntireRow.Hidden = True
ActiveSheet.Paste
Then just put the 'skip:' term somewhere just before the next (I cant see it in your code, is it because this is just a section of a larger sub?)
Make a function that check a list with the wanted values after put them in a sheet.
Function checking(value as string)
Dim x as integer
Dim numWantedvalues as Integer
numWantedvalues = WorksheetFunction.CountA(ThisWorkbook.Sheets("Sheet2").Range("A:A"))
For x = 1 to numWantedvalues
If ThisWorkbook.Sheets("Sheet2").Range("A" & x) = value Then
checking = True
End If
Next x
end function
Then introduce the function in your code:
If checking(arValue) = True Then
'Actions that you want to do
End If

Easier way of Importing data into excel - collections?

Is there an easier way of importing data into an excel array or other data structure? I've tried researching collections but I have found the documentation hard to comprehend.
http://www.functionx.com/vbaexcel/objects/Lesson6.htm
https://msdn.microsoft.com/en-us/library/f26wd2e5%28v=vs.100%29.aspx
The code I have below opens a select file and searches for the column header and then loops through each row storing the data according to header and row variables, I've done this method for many macros in the past but now I am dealing with many many columns and I'm looking for a more advanced way?
Sub Import_NAVRec()
MyPath = Range("b2") 'Defines cell that contains path to source file
Workbooks.Open (MyPath) 'Opens file
Set tempbook = ActiveWorkbook 'Names workbook
LR = Range("A65000").End(xlUp).Row 'finds last row in sourcefile
ReDim aNavRec(1 To LR, 1 To 4) 'Defines NAV Rec array
nRow = 0
cName = "Accounting Basis"
CA = Cells.Find(What:=UCase(cName), After:=ActiveCell, LookIn:=xlFormulas, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext).Column
cName = "Accounting Date"
cB = Cells.Find(What:=UCase(cName), After:=ActiveCell, LookIn:=xlFormulas, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext).Column
cName = "Asset Currency"
cC = Cells.Find(What:=UCase(cName), After:=ActiveCell, LookIn:=xlFormulas, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext).Column
For r = 2 To LR
'If Cells(r, cB) = "Trading Gain Loss" Then
nRow = nRow + 1
aNavRec(nRow, 1) = Cells(r, CA) 'Fund Number
aNavRec(nRow, 2) = Cells(r, cB) 'Ledger
aNavRec(nRow, 3) = Cells(r, cC) 'Balance change
'End If
Next r
tempbook.Close
End Sub
Sub Print_output()
Sheets("Output").Select
Set Destination = Range("a2")
Destination.Resize(UBound(aNavRec, 1) + 1, UBound(aNavRec, 2)).Value = aNavRec
End Sub
The only thing we can help you eliminate is the for loop in the middle of you code. The rest seems to be necessary.
Option Explicit
Sub Import_NAVRec()
Dim LR As Long
Dim MyPath As String
Dim aNavRec As Variant 'Defines NAV Rec array
Dim tempbook As Workbook
Dim CA As Long, cB As Long, cC As Long
MyPath = Range("B2") 'Defines cell that contains path to source file
Workbooks.Open (MyPath) 'Opens file
Set tempbook = ActiveWorkbook 'Names workbook
LR = Range("A65000").End(xlUp).Row 'finds last row in sourcefile
cName = "Accounting Basis"
CA = Cells.Find(What:=UCase(cName), After:=ActiveCell, LookIn:=xlFormulas, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext).Column
cName = "Accounting Date"
cB = Cells.Find(What:=UCase(cName), After:=ActiveCell, LookIn:=xlFormulas, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext).Column
cName = "Asset Currency"
cC = Cells.Find(What:=UCase(cName), After:=ActiveCell, LookIn:=xlFormulas, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext).Column
aNavRec = Application.Index(Range("A:AZ"), Application.Evaluate("Row(1:" & LR & ")"), Array(CA, cB, cC))
tempbook.Close
End Sub
With Option Explicit some more Dim were necessary (which I included in the above soluion).
Note: just found this solution here: use variable for row_num application.index

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

Excel VBA Replace with Array Groups

Right now I am using a horribly inefficient way for a replacement function:
Dim Replacement As String
Dim rngRepVal As Object
Set rngRepVal = Sheets("data").Range(Cells(1, 3), Cells(intRowLast, 3))
Replacement = ActiveCell.Value
rngRepVal.Replace What:="123", Replacement:="ABC", LookAt:=xlWhole, SearchOrder:=xlByRows, MatchCase:=False
rngRepVal.Replace What:="234", Replacement:="ABC", LookAt:=xlWhole, SearchOrder:=xlByRows, MatchCase:=False
rngRepVal.Replace What:="456", Replacement:="DEF", LookAt:=xlWhole, SearchOrder:=xlByRows, MatchCase:=False
... [goes on for 50 lines]
Set rngRepVal = Nothing
I am wondering if this can be achieved with arrays. Something like:
Dim aWhat() As String
Dim aReplacement() As String
aWhat = Split("ABC|DEF|GHI|JKL", "|")
aReplacement = Split(Array("123", 456")|Array("789","1000"), "|") '<-not sure how to organise this
Essentially 123 & 456 get replaced by ABC, 789 & 1000 get replaced by DEF etc. in a replace loop> Any insights on how to organise the two arrays? Thanks!
Your Replace(s) are fine - its the cell by cell loop and selection that is inefficient. Try something like this for three replaces over the entire range at once.
Sub Recut()
Dim rng1 As Range
Set rng1 = Sheets("data").Range(Sheets("data").Cells(1, 3), Sheets("data").Cells(Rows.Count, 3).End(xlUp))
With rng1
.Replace What:="123", Replacement:="ABC", LookAt:=xlWhole, SearchOrder:=xlByRows, MatchCase:=False
.Replace What:="234", Replacement:="ABC", LookAt:=xlWhole, SearchOrder:=xlByRows, MatchCase:=False
.Replace What:="456", Replacement:="DEF", LookAt:=xlWhole, SearchOrder:=xlByRows, MatchCase:=False
End With
End Sub
I would try this:
aWhat=Split("ABC|ABC|DEF|DEF|GHI|GHI...","|")
aReplacement=Split("123|456|789|.....","|")
For i=1 to UBound(aWhat)
rngRepVal.Replace what:=aWhat[i], Replacement:=aReplacement[i], ....
Next i
Just make sure there's the same number of elements in both arrays.
I think found it, by accident:
Dim aOld() As Variant
Dim aNew() As Variant
Dim Group As Variant
Dim Word As Variant
Dim y As Long
aNew = Array("ABC", "DEF", "GHI", "JKL")
aOld = Array(Array("123", "456"), Array("789", "1000"))
With Range("A:A")
For Each Group In aOld
For Each Word In Group
.Replace What:=Word, Replacement:=aNew(y), LookAt:=xlWhole, SearchOrder:=xlByRows, MatchCase:=False
Next
y = y + 1
Next
End With

Resources