Add specific CSV to workbook in VBA - excel

I have a an Excel workbook and I want to add a specific CSV as a new sheet and then convert it in a table.
Here is my VBA code, this works fine, the problem is that then when I want to convert the sheet into a tab then Excel give me this error:
A Table cannot overlap a range that contains a Pivot Table report,query results, protected cells or another table.
Sub Macro8()
'
'
Dim strPath As String
Dim strFile As String
'
strPath = "Q:\myfolder\"
strFile = Dir(strPath & "filename" & Format(Now(), "YYYYMMDD") & ".csv")
Do While strFile <> ""
With ActiveWorkbook.Worksheets.Add
With .QueryTables.Add(Connection:="TEXT;" & strPath & strFile, _
Destination:=.Range("A1"))
.Parent.Name = Replace(strFile, ".csv", "")
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = False
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = True
.TextFileSpaceDelimiter = False
.TextFileColumnDataTypes = Array(1)
.TextFileTrailingMinusNumbers = True
.Refresh BackgroundQuery:=False
End With
End With
strFile = Dir
Loop
End Sub
Sub A_SelectAllMakeTable()
Dim tbl As ListObject
Dim rng As Range
Set rng = Range(Range("A1"), Range("A1").SpecialCells(xlLastCell))
Set tbl = ActiveSheet.ListObjects.Add(xlSrcRange, rng, , xlYes)
tbl.Name = "OPEN"
tbl.TableStyle = "TableStyleMedium15"
End Sub
Can someone help me please?

A Table cannot overlap a range that contains a Pivot Table report,query results, protected cells or another table.
You need to break the querytable connection first else you will get the error that you are getting. is this what you are trying?
Sub A_SelectAllMakeTable()
Dim tbl As ListObject
Dim rng As Range
Dim ws As Worksheet
Dim lCol As Long, lRow As Long
Set ws = ActiveSheet
With ws
'~~> Delete the connection
For Each Cn In .QueryTables
Cn.Delete
Next Cn
If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
'~~> Find last row and column to construct your range
lRow = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
lCol = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Column
Set rng = .Range(.Cells(1, 1), .Cells(lRow, lCol))
Set tbl = ActiveSheet.ListObjects.Add(xlSrcRange, rng, , xlYes)
tbl.Name = "OPEN"
tbl.TableStyle = "TableStyleMedium15"
End If
End With
End Sub

Related

Error message when opening a copied workbook

I create a copy of a workbook and paste the values as Paste:=xlPasteValues
When I open the workbook with the xlPasteValues values, I get an error message (see attached picture).
What am I doing wrong? Thank you very much for your appreciated support.
Sub CopyPasteValuesInAllWorksheets()
With Application
.Calculation = xlCalculationManual
.DisplayStatusBar = False
.EnableEvents = False
.ScreenUpdating = False
End With
Dim ws As Worksheet
Dim LastRow As Long, LastColumn As Long
For Each ws In Worksheets
Dim rng As Range
LastRow = ws.Cells.Find(what:="*", _
lookat:=xlPart, _
LookIn:=xlFormulas, _
searchorder:=xlByRows, _
searchdirection:=xlPrevious).Row
LastColumn = ws.Cells.Find(what:="*", _
lookat:=xlPart, _
LookIn:=xlFormulas, _
searchorder:=xlByColumns, _
searchdirection:=xlPrevious).Column
Set rng = ws.Range(ws.Cells(1, 1), ws.Cells(LastRow, LastColumn))
rng.Copy
rng.PasteSpecial Paste:=xlPasteValues
Next ws
Application.CutCopyMode = False
With Application
.DisplayStatusBar = True
.EnableEvents = True
.ScreenUpdating = True
End With
Dim fName As Variant
Dim currentDate As String
currentDate = Format(Date, "YYYY-MM-DD")
fName = Application.GetSaveAsFilename("......\" _
& "...." & " " & currentDate & ".xlsx", _
"Excel files,*.xlsx", _
1, _
"Select your folder and filename")
'exit procedure if the user didn't save the file
If TypeName(fName) = "Boolean" Then Exit Sub
Application.DisplayAlerts = False
ThisWorkbook.SaveAs FileName:=fName, FileFormat:=51
Application.DisplayAlerts = True
End Sub

Replace Values in Range

I've tried to do this replacement in two different ways (first attempt commented below), but it ends up replacing everything on the sheet, instead:
Sub NoNullSaveCSV()
Dim WB As Workbook
Dim WS As Worksheet
Dim find1 As Variant
Dim rplc1 As Variant
Dim find2 As Variant
Dim rplc2 As Variant
Dim Rng As Range
Application.Workbooks.Add xlWBATWorksheet
Set WB = ActiveWorkbook
Set WS = ActiveSheet
With ThisWorkbook.Worksheets("PedidosTratados")
.Range("A3:DW1000").Copy
WS.Range("A1").PasteSpecial xlPasteValues
End With
WS.Range("A1").Value = "FilterCol"
WS.Columns.AutoFilter Field:=1, Criteria1:=""
WS.UsedRange.SpecialCells(xlCellTypeVisible).EntireRow.Delete
WS.AutoFilterMode = False
ReplaceCount = ReplaceCount + Application.WorksheetFunction.CountIf(WS.Cells, "*" & fnd1 & "*")
'+ Application.WorksheetFunction.CountIf(WS.Cells, "*" & fnd2 & "*")
fnd1 = "7.9000"
rplc1 = "7.900"
fnd2 = "9.9000"
rplc2 = "9.900"
With WS
.Range("AT2:DW1000").Replace fnd1, rplc1
.Range("AT2:DW1000").Replace fnd2, rplc2
'.Cells.Replace what:=fnd1, Replacement:=rplc1, _
'LookAt:=xlPart, SearchOrder:=xlByColumns, MatchCase:=False, _
'SearchFormat:=False, ReplaceFormat:=False
'.Cells.Replace what:=fnd2, Replacement:=rplc2, _
'LookAt:=xlPart, SearchOrder:=xlByColumns, MatchCase:=False, _
'SearchFormat:=False, ReplaceFormat:=False
End With
WB.SaveAs fileName:=ThisWorkbook.Path & "\Pedidos.csv", FileFormat:=xlCSV
WB.Close False
MsgBox "Após a pesquisa, foram feitas " & ReplaceCount & " substituições."
End Sub
Could you anyone tell me why this is not restraining replacement to the specified range?
Thank you!

How to import multiple text files into columns of single excel worksheet

I have been trying to figure out how to take several hundred tab-delimited text files and import the data into subsequent columns of a single excel worksheet. The text files contain I(V) data with two columns and a header. I have found code/manipulated it to be able to remove the header and import into individual worksheets within a workbook but would like to be able to get the two columns of data from each worksheet into a single worksheet (i.e. columns from first text file to columns A & B of one worksheet, columns from second text file to columns C & D, etc.). Here is the code I am currently using:
Sub CombineTextFiles()
Dim FilesToOpen
Dim x As Integer
Dim wkbAll As Workbook
Dim wkbTemp As Workbook
Dim sDelimiter As String
On Error GoTo ErrHandler
Application.ScreenUpdating = False
sDelimiter = "|"
FilesToOpen = Application.GetOpenFilename _
(FileFilter:="Text Files (*.txt), *.txt", _
MultiSelect:=True, Title:="Text Files to Open")
If TypeName(FilesToOpen) = "Boolean" Then
MsgBox "No Files were selected"
GoTo ExitHandler
End If
x = 1
Set wkbTemp = Workbooks.Open(Filename:=FilesToOpen(x))
wkbTemp.Sheets(1).Copy
Set wkbAll = ActiveWorkbook
wkbTemp.Close (False)
wkbAll.Worksheets(x).Columns("A:A").TextToColumns _
Destination:=Range("A1"), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, _
ConsecutiveDelimiter:=False, _
Tab:=True, Semicolon:=False, _
Comma:=False, Space:=False, _
Other:=True, OtherChar:="|"
Rows("1:20").Select
Selection.Delete Shift:=xlUp
x = x + 1
While x <= UBound(FilesToOpen)
Set wkbTemp = Workbooks.Open(Filename:=FilesToOpen(x))
With wkbAll
wkbTemp.Sheets(1).Move After:=.Sheets(.Sheets.Count)
.Worksheets(x).Columns("A:A").TextToColumns _
Destination:=Range("A1"), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, _
ConsecutiveDelimiter:=False, _
Tab:=False, Semicolon:=False, _
Comma:=False, Space:=False, _
Other:=True, OtherChar:=sDelimiter
Rows("1:20").Select
Selection.Delete Shift:=xlUp
End With
x = x + 1
Wend
ExitHandler:
Application.ScreenUpdating = True
Set wkbAll = Nothing
Set wkbTemp = Nothing
Exit Sub
ErrHandler:
MsgBox Err.Description
Resume ExitHandler
End Sub
Here is an example of one of my I(V) data files:
Notes:
Timestamp: 7/19/2018 8:36:11 AM
Channel: Channel A
NPLC: 1
Current Limit: 0.010000
Pulse Mode: 0
Bias Pulses: 1
Bias Level: 0.000000
Settling Time: 0.500000
Voltage (V) Current (A)
-1.00000E+0 -6.95885E-7
-9.50000E-1 -6.47828E-7
-9.00000E-1 -6.06955E-7
-8.50000E-1 -5.53913E-7
-8.00000E-1 -5.00038E-7
-7.50000E-1 -4.51646E-7
-7.00000E-1 -4.02903E-7
-6.50000E-1 -3.58851E-7
-6.00000E-1 -3.19926E-7
-5.50000E-1 -2.73332E-7
-5.00000E-1 -2.33349E-7
-4.50000E-1 -1.99018E-7
-4.00000E-1 -1.62825E-7
-3.50000E-1 -1.31703E-7
-3.00000E-1 -1.04510E-7
-2.50000E-1 -8.06238E-8
-2.00000E-1 -5.88286E-8
-1.50000E-1 -4.14340E-8
-1.00000E-1 -2.58151E-8
-5.00000E-2 -1.24138E-8
0.00000E+0 5.52116E-11
5.00000E-2 1.26769E-8
1.00000E-1 2.64685E-8
1.50000E-1 4.17401E-8
2.00000E-1 5.97095E-8
2.50000E-1 7.98343E-8
3.00000E-1 1.02119E-7
3.50000E-1 1.28176E-7
4.00000E-1 1.57270E-7
4.50000E-1 1.89915E-7
5.00000E-1 2.29916E-7
5.50000E-1 2.72104E-7
6.00000E-1 3.35173E-7
6.50000E-1 4.53464E-7
7.00000E-1 6.12379E-7
7.50000E-1 7.97423E-7
8.00000E-1 9.75624E-7
8.50000E-1 1.16841E-6
9.00000E-1 1.34435E-6
9.50000E-1 1.52710E-6
1.00000E+0 1.75166E-6
1.00000E+0 1.81262E-6
9.50000E-1 1.72918E-6
9.00000E-1 1.63206E-6
8.50000E-1 1.52714E-6
8.00000E-1 1.42523E-6
7.50000E-1 1.32162E-6
7.00000E-1 1.21624E-6
6.50000E-1 1.11347E-6
6.00000E-1 1.00770E-6
5.50000E-1 9.05824E-7
5.00000E-1 8.08058E-7
4.50000E-1 7.09499E-7
4.00000E-1 6.14927E-7
3.50000E-1 5.26256E-7
3.00000E-1 4.38557E-7
2.50000E-1 3.53943E-7
2.00000E-1 2.74731E-7
1.50000E-1 1.98096E-7
1.00000E-1 1.27457E-7
5.00000E-2 6.16247E-8
0.00000E+0 -8.63841E-11
-5.00000E-2 -5.78634E-8
-1.00000E-1 -1.15769E-7
-1.50000E-1 -1.73858E-7
-2.00000E-1 -2.33503E-7
-2.50000E-1 -2.94364E-7
-3.00000E-1 -3.59336E-7
-3.50000E-1 -4.24816E-7
-4.00000E-1 -4.92460E-7
-4.50000E-1 -5.61514E-7
-5.00000E-1 -6.32542E-7
-5.50000E-1 -7.06702E-7
-6.00000E-1 -7.83559E-7
-6.50000E-1 -8.63077E-7
-7.00000E-1 -9.49685E-7
-7.50000E-1 -1.03839E-6
-8.00000E-1 -1.12932E-6
-8.50000E-1 -1.22503E-6
-9.00000E-1 -1.31770E-6
-9.50000E-1 -1.42892E-6
-1.00000E+0 -1.53654E-6
None of the header information is needed, which is why I am currently just deleting the first 20 rows. I have basic programming experience but very little with VBA. Any help with this particular problem is greatly appreciated!
-Tory
Try so:
Sub CombineTextFiles()
Dim FilesToOpen
Dim x As Integer
Dim wkbAll As Workbook
Dim wkbTemp As Workbook
Dim sDelimiter As String
On Error GoTo ErrHandler
Application.ScreenUpdating = False
sDelimiter = "|"
Set wkbAll = ActiveWorkbook
FilesToOpen = Application.GetOpenFilename _
(FileFilter:="Text Files (*.txt), *.txt", _
MultiSelect:=True, Title:="Text Files to Open")
If TypeName(FilesToOpen) = "Boolean" Then
MsgBox "No Files were selected"
GoTo ExitHandler
End If
iDestCol=1
For x = 0 to Ubound(FilesToOpen)
Set wkbTemp = Workbooks.Open(Filename:=FilesToOpen(x))
wkbTemp.Columns("A:A").TextToColumns _
Destination:=Range("A1"), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, _
ConsecutiveDelimiter:=False, _
Tab:=True, Semicolon:=False, _
Comma:=False, Space:=False, _
Other:=True, OtherChar:="|"
wbkTemp.Range("A:B").Copy Destination:=wkbAll.Cells(1, iDestCol)
wkbTemp.Close (False)
iDestCol = iDestCol + 2
Next
Rows("1:20").Delete Shift:=xlUp
ExitHandler:
Application.ScreenUpdating = True
Exit Sub
ErrHandler:
MsgBox Err.Description
Resume ExitHandler
End Sub
So, I managed to get two macros coded to do what I need. I have one for pulling the data in from selected text files into individual sheets and another to consolidate the sheets into columns of a single sheet. The code for the first macro is here:
Sub TextToSheets()
Dim FilesToOpen
Dim x As Integer
Dim wkbAll As Workbook
Dim wkbTemp As Workbook
Dim sDelimiter As String
On Error GoTo ErrHandler
Application.ScreenUpdating = False
sDelimiter = "|"
FilesToOpen = Application.GetOpenFilename _
(FileFilter:="Text Files (*.txt), *.txt", _
MultiSelect:=True, Title:="Text Files to Open")
If TypeName(FilesToOpen) = "Boolean" Then
MsgBox "No Files were selected"
GoTo ExitHandler
End If
x = 1
Name = Dir(FilesToOpen(x))
Set wkbTemp = Workbooks.Open(Filename:=FilesToOpen(x))
wkbTemp.Sheets(1).Copy
Set wkbAll = ActiveWorkbook
wkbTemp.Close (False)
wkbAll.Worksheets(x).Columns("A:A").TextToColumns _
Destination:=Range("A1"), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, _
ConsecutiveDelimiter:=False, _
Tab:=True, Semicolon:=False, _
Comma:=False, Space:=False, _
Other:=True, OtherChar:="|"
Range("A19:B19").Select
ActiveCell.FormulaR1C1 = Name
Range("A20").Select
ActiveCell.FormulaR1C1 = "Voltage (V)"
Range("B20").Select
ActiveCell.FormulaR1C1 = "Current (A)"
Rows("1:18").Select
Selection.Delete Shift:=xlUp
x = x + 1
While x <= UBound(FilesToOpen)
Name = Dir(FilesToOpen(x))
Set wkbTemp = Workbooks.Open(Filename:=FilesToOpen(x))
With wkbAll
wkbTemp.Sheets(1).Move after:=.Sheets(.Sheets.Count)
.Worksheets(x).Columns("A:A").TextToColumns _
Destination:=Range("A1"), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, _
ConsecutiveDelimiter:=False, _
Tab:=False, Semicolon:=False, _
Comma:=False, Space:=False, _
Other:=True, OtherChar:=sDelimiter
Range("A19:B19").Select
ActiveCell.FormulaR1C1 = Name
Range("A20").Select
ActiveCell.FormulaR1C1 = "Voltage (V)"
Range("B20").Select
ActiveCell.FormulaR1C1 = "Current (A)"
Rows("1:18").Select
Selection.Delete Shift:=xlUp
End With
x = x + 1
Wend
ExitHandler:
Application.ScreenUpdating = True
Set wkbAll = Nothing
Set wkbTemp = Nothing
Exit Sub
ErrHandler:
MsgBox Err.Description
Resume ExitHandler
End Sub
And for the second here:
Sub CombineSheetsToColumns()
Application.DisplayAlerts = False
On Error Resume Next
Sheets("Summary").Delete
Application.DisplayAlerts = True
n = Application.Worksheets.Count
Sheets.Add.Name = "Summary"
Sheets("Summary").Move after:=Worksheets(Worksheets.Count)
Set MerPos = Range(Cells(1, 2), Cells(1, 3))
Dim sh As Worksheet
For Each sh In ActiveWorkbook.Worksheets
If sh.Name <> "Summary" And sh.Name <> Sheets(n + 1).Name Then
Set col = Columns(Columns.Count).End(xlToLeft)
sh.Range("A:A,B:B").Copy Destination:=Sheets("Summary").Range(col, col).Offset(0, 1)
MerPos.Select
Selection.Merge
Set MerPos = Range(MerPos.Offset(0, 1), MerPos.Offset(0, 2))
End If
Next sh
Columns("A:A").Select
Selection.Delete Shift:=xlToLeft
Sheets("Summary").Select
Cells.HorizontalAlignment = xlCenter
Columns.AutoFit = xlColumn
End Sub
I added a few lines for adding text and formatting but shouldn't be too hard to get it working for whatever you may need to use it for. Thanks for all the help!
If you want to copy/paste data across a sheet, run the code below.
Sub ReadFilesIntoActiveSheet()
Dim fso As FileSystemObject
Dim folder As folder
Dim file As file
Dim FileText As TextStream
Dim TextLine As String
Dim Items() As String
Dim i As Long
Dim cl As Range
' Get a FileSystem object
Set fso = New FileSystemObject
' get the directory you want
Set folder = fso.GetFolder("C:\Users\Excel\Desktop\Coding\LinkedIn\Import All Text Files Into One Single Sheet with File Name in Column A\")
' set the starting point to write the data to
'Set cl = ActiveSheet.Cells(1, 1)
Dim sht As Worksheet
Dim LastRow As Long
Set sh = ActiveSheet
' Loop thru all files in the folder
For Each file In folder.Files
' Write file-name
LastRow = sh.Cells(sh.Rows.Count, "A").End(xlUp).Row + 1
Range("A" & LastRow).Select
ActiveCell = file.Name
' open the file
Set txtFile = fso.OpenTextFile(file)
col = 2
Do While Not txtFile.AtEndOfStream
dat = Application.Transpose(Application.Index(Split(txtFile.ReadLine, ","), 1, 0))
sh.Cells(LastRow, col).Resize(UBound(dat), 1) = dat
col = col + 1
Loop
' Clean up
txtFile.Close
'Range(cl.Address).Offset(1, 0).Select
Next file
Set FileText = Nothing
Set file = Nothing
Set folder = Nothing
Set fso = Nothing
End Sub
If you want to copy/paste data down a sheet, run the code below.
Sub ReadFilesIntoActiveSheet()
Dim fso As FileSystemObject
Dim folder As folder
Dim file As file
Dim FileText As TextStream
Dim TextLine As String
Dim Items() As String
Dim i As Long
Dim cl As Range
' Get a FileSystem object
Set fso = New FileSystemObject
' get the directory you want
Set folder = fso.GetFolder("C:\Users\Excel\Desktop\Coding\LinkedIn\Import All Text Files Into One Single Sheet with File Name in Column A\")
' set the starting point to write the data to
Set cl = ActiveSheet.Cells(2, 1)
' Loop thru all files in the folder
For Each file In folder.Files
' Write file-name
cl.Value = file.Name
' Open the file
Set FileText = file.OpenAsTextStream(ForReading)
' Read the file one line at a time
Do While Not FileText.AtEndOfStream
TextLine = FileText.ReadLine
' Parse the line into | delimited pieces
Items = Split(TextLine, "|")
' Put data on one row in active sheet
For i = 0 To UBound(Items)
cl.Offset(0, 1 + i).Value = Items(i)
Next
' Move to next row
Set cl = cl.Offset(1, 0)
Loop
' Clean up
FileText.Close
Next file
Set FileText = Nothing
Set file = Nothing
Set folder = Nothing
Set fso = Nothing
End Sub

copy rows between header and the last row

I found and modified a code that works pretty well but I am struggling with Set CopyRng = sh.Range("A11:AI15") . What I want to do is to create a dynamic range that will copy values from first table from each worksheet between header called Language and last row in table called Total. Some cells are merged in the table (default template) and there are empty columns in the table (so .CurrentRegion doesn't work).
Function LastRow(sh As Worksheet)
On Error Resume Next
LastRow = sh.Cells.Find(What:="*", _
After:=sh.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
On Error GoTo 0
End Function
Function LastCol(sh As Worksheet)
On Error Resume Next
LastCol = sh.Cells.Find(What:="*", _
After:=sh.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Column
On Error GoTo 0
End Function
Sub CopyRangeFromMultiWorksheets()
Dim sh As Worksheet
Dim DestSh As Worksheet
Dim Last As Long
Dim CopyRng As Range
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
Set DestSh = ActiveWorkbook.Worksheets("test")
' Loop through all worksheets and copy the data to the
' summary worksheet.
For Each sh In ActiveWorkbook.Worksheets
If sh.Name Like "test*" Then
Last = LastRow(DestSh)
' Specify the range to place the data.
Set CopyRng = sh.Range("A11:AI15")
CopyRng.Copy
With DestSh.Cells(Last + 1, "A")
.PasteSpecial
Application.CutCopyMode = False
End With
DestSh.Cells(Last + 1, "A").Resize(CopyRng.Rows.Count).Value = sh.Range("F8")
DestSh.Cells(Last + 1, "AK").Resize(CopyRng.Rows.Count).Formula = "=AG10*3%"
DestSh.Cells(Last + 1, "AL").Resize(CopyRng.Rows.Count).Formula = "=AG10+AK10"
End If
Next
ExitTheSub:
Application.Goto DestSh.Cells(1)
DestSh.Columns.AutoFit
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
Regards,
Here is a function that will return you the range. Parameters explained:
oW = The worksheet you want to get the range from
sStartColHeader = Holds the name of the header column you want to start the range from (i.e. in your example this would be "Language")
Function GetRange(ByVal oW As Worksheet, ByVal sStartColHeader As String) As Range
Dim oTotRng As Range: Set oTotRng = oW.Cells.Find("total", oW.Cells(1, 1), xlValues, xlPart, xlByRows, xlNext, False, , False)
Dim oLan As Range
Set oLan = oW.Cells.Find(sStartColHeader, oW.Cells(1, 1), xlValues, xlPart, xlByRows, xlNext, False, , False)
If oLan Is Nothing Then
Set GetRange = Nothing
Else
Set GetRange = Range(oLan.Offset(1, 0), oTotRng.Offset(0, 1))
End If
End Function
How to use this function:
In CopyRangeFromMultiWorksheets function, change Set CopyRng = sh.Range("A11:AI15") to Set CopyRng = GetRange(sh, "Language"). Then have an If condition to check if a range was returned. For example:
Set CopyRng = GetRange(sh, "Language")
If CopyRng Is Nothing Then
' your exception code here as range was not returned
Else
' rest of your code here as a range was returned
End If
NOTE: Presumption is that the actual total amount in the sheet is in the cell to the right of the cell that contains the text Total. So if "H10" has text Total, actual total is held in cell "I10"
I have found a solution that works great. See the code below:
Sub CopyRangeFromMultiWorksheets()
Dim sh As Worksheet
Dim DestSh As Worksheet
Dim Last As Long
Dim CopyRng As Range
Dim findrow As Long, findrow2 As Long
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
Set DestSh = ThisWorkbook.Worksheets("Summary")
For Each sh In ActiveWorkbook.Worksheets
If sh.Name <> DestSh.Name Then
Last = LastRow(DestSh)
'this method doesn't work with merged cells thhat is why I have to unmerge them first.
sh.Range("B10:B200").UnMerge
findrow = sh.Range("B:B").Find("Language Pair", sh.Range("B1")).Row
findrow2 = sh.Range("B:B").Find("Total", sh.Range("B" & findrow)).Row
Set CopyRng = sh.Range("A" & findrow + 1 & ":AJ" & findrow2 - 1)
CopyRng.Copy
With DestSh.Cells(Last + 1, "B")
.PasteSpecial
Application.CutCopyMode = False
End With
DestSh.Cells(Last + 1, "A").Resize(CopyRng.Rows.Count).Value = sh.Range("F8")
DestSh.Cells(Last + 1, "AK").Resize(CopyRng.Rows.Count).Formula = "=AG10*3%"
DestSh.Cells(Last + 1, "AL").Resize(CopyRng.Rows.Count).Formula = "=AG10+AK10"
End If
Next
ExitTheSub:
Application.Goto DestSh.Cells(1)
DestSh.Columns.AutoFit
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
Function LastRow(sh As Worksheet)
On Error Resume Next
LastRow = sh.Cells.Find(What:="*", _
After:=sh.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
On Error GoTo 0
End Function
Function LastCol(sh As Worksheet)
On Error Resume Next
LastCol = sh.Cells.Find(What:="*", _
After:=sh.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Column
On Error GoTo 0
End Function

How to accelerate an Excel VB Macro

I am trying to accelerate my Excel VB Macro.
I have tried the 5 alternatives below.
But I wonder if I could shorten the execution further.
I found 2 alternatives in User Blogs which I could not get to work.
One alternative is also found in a User Blog but do not understand.
Sub AccelerateMacro()
'
' v1 052817 by eb+mb
' Macro to copy as fast as possible sheet from one workbook into another workbooks
' Declarations for variables are not shown to make code example more legible
' Macro is stored in and run from "DestinationWorkBook.xlsm"
StartTime = Timer
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Alternative = "First"
If Alternative = "First" Then
Workbooks.Open Filename:="SourceWorkBook.xls"
Cells.Select
Selection.Copy
Windows("DestinationWorkBook.xlsm").Activate
Sheets("DestinationSheet").Select
Range("A1").Select
ActiveSheet.Paste
Windows("SourceWorkBook.xls").Activate
ActiveWorkbook.Close
End If
If Alternative = "Second" Then
Workbooks.Open Filename:="SourceWorkBook.xls", ReadOnly:=True
Cells.Select
Selection.Copy
Windows("DestinationWorkBook.xlsm").Activate
Sheets("DestinationSheet").Select
Range("A1").Select
ActiveSheet.Paste
Workbooks("SourceWorkBook.xls").Close SaveChanges:=False
End If
If Alternative = "Third" Then
' I could not get this alternative to work
Workbooks.Open("SourceWorkBook.xls").Worksheets("SourceSheet").Copy
Workbooks.Open("DestinationWorkBook.xlsm").Worksheets("DestinationSheet").Range("A1").PasteSpecial
End If
If Alternative = "Fourth" Then
' I could not get this alternative to work
Workbooks.Open("DestinationWorkBook.xlsm").Worksheets("DestinationSheet").Range("A1") = Workbooks.Open("SourceWorkBook.xls").Worksheets("SourceSheet")
End If
If Alternative = "Fifth" Then
' I don't understand the code in this alternative
Dim wbIn As Workbook
Dim wbOut As Workbook
Dim rSource As Range
Dim rDest As Range
Set wbOut = Application.Workbooks.Open("DestinationWorkBook.xlsm")
Set wbIn = Application.Workbooks.Open("SourceWorkBook.xls")
With wbIn.Sheets("SourceSheet").UsedRange
wbOut.Sheets("DestinationSheet").Range("A1").Resize(.Rows.Count, .Columns.Count) = .Value
End With
SecondsElapsed = Round(Timer - StartTime, 2)
MsgBox "This code ran successfully in " & SecondsElapsed & " seconds", vbInformation
End Sub
Instead of using UsedRange, find the actual Last Row and Last Column and use that range. UsedRange may not be the range that you think it is :). You may want to see THIS for an explanation.
See this example (UNTESTED)
Sub Sample()
Dim wbIn As Workbook, wbOut As Workbook
Dim rSource As Range
Dim lRow As Long, LCol As Long
Dim LastCol As String
Set wbOut = Workbooks.Open("DestinationWorkBook.xlsm")
Set wbIn = Workbooks.Open("SourceWorkBook.xls")
With wbIn.Sheets("SourceSheet")
'~~> Find Last Row
lRow = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
'~~> Find Last Column
LCol = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Column
'~~> Column Number to Column Name
LastCol = Split(Cells(, LCol).Address, "$")(1)
'~~> This is the range you want
Set rSource = .Range("A1:" & LastCol & lRow)
'~~> Get the values across
wbOut.Sheets("DestinationSheet").Range("A1:" & LastCol & lRow).Value = _
rSource.Value
End With
End Sub

Resources