This question already has answers here:
How to avoid using Select in Excel VBA
(15 answers)
Closed 3 years ago.
I have created a VBA macro in excel. It works; however, every forum I read states I should avoid using Select. As I am a newbie, I do not know how to implement it nor how it would work.
The code does the following:
Copy contents in Column B to Column E, then delete Column B
Column E then becomes Column D
Format all cells in Column D to wrap text
Use Data text to Column feature on Column D
Delimiter based on line breaks. (Other: CTRL J)
Sub TestRun()
Columns("B:B").Select
Application.CutCopyMode = False
Selection.Copy
Columns("E:E").Select
ActiveSheet.Paste
Columns("B:B").Select
Application.CutCopyMode = False
Selection.Delete Shift:=xlToLeft
Columns("D:D").Select
With Selection
.HorizontalAlignment = xlGeneral
.VerticalAlignment = xlBottom
.WrapText = True
.Orientation = 0
.AddIndent = False
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = False
End With
Selection.ColumnWidth = 25.13
Selection.TextToColumns Destination:=Range("D1"), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=False, _
Semicolon:=False, Comma:=False, Space:=False, Other:=True, OtherChar _
:="" & Chr(10) & "", FieldInfo:=Array(Array(1, 1), Array(2, 1), Array(3, 1), Array(4, 1), Array(5, _
1), Array(6, 1), Array(7, 1), Array(8, 1), Array(9, 1), Array(10, 1), Array(11, 1), Array(12 _
, 1), Array(13, 1), Array(14, 1), Array(15, 1), Array(16, 1), Array(17, 1), Array(18, 1)), _
TrailingMinusNumbers:=True
End Sub
Simply just replace .Select with the Method (action) or Property (attribute) that you will be using. Then delete all unecessary actions that Select would normally do. For example:
Sub TestRun()
Columns("B:B").Copy Destination:=Columns("E:E")
Columns("B:B").Delete Shift:=xlToLeft
With Columns("D:D")
.HorizontalAlignment = xlGeneral
.VerticalAlignment = xlBottom
.WrapText = True
.Orientation = 0
.AddIndent = False
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = False
.ColumnWidth = 25.13
.TextToColumns Destination:=Range("D1"), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=False, _
Semicolon:=False, Comma:=False, Space:=False, Other:=True, OtherChar _
:="" & Chr(10) & "", FieldInfo:=Array(Array(1, 1), Array(2, 1), Array(3, 1), Array(4, 1), Array(5, _
1), Array(6, 1), Array(7, 1), Array(8, 1), Array(9, 1), Array(10, 1), Array(11, 1), Array(12 _
, 1), Array(13, 1), Array(14, 1), Array(15, 1), Array(16, 1), Array(17, 1), Array(18, 1)), _
TrailingMinusNumbers:=True
End With
End Sub
Here is a simple example using the With statement with out using variables to move col2 to col4.
'Identify your workbook and sheet, change the sheet name as needed
With ThisWorkbook.Sheets("Sheet1")
'First - Cut col2
.Columns(2).EntireColumn.Cut
'Second - Insert col2 at col5 shifting the current col5 to the right.
.Columns(5).EntireColumn.Insert Shift:=xlRight
'col3 etc. will then shift left because col2 was cut and moved to col5
End With
You can use With Columns(4) inside the above With statement to format the column, try to write the code and if you have any more questions then please ask.
Related
I use a simple macro, insert a "txt" file and then split it into columns
Sub POR_Import()
Dim ws As Worksheet, strFile As String
Call Smaz_vstup_POR
Set ws = ActiveWorkbook.Sheets("POR_IMPORT") 'set to current worksheet name
strFile = Application.GetOpenFilename("Text Files (*.*),*.*", , "Please select text file...")
With ws.QueryTables.Add(Connection:="TEXT;" & strFile, Destination:=ws.Range("A1"))
.TextFileParseType = xlDelimited
.TextFileCommaDelimiter = True
.Refresh
Call SplitPOR
i = MsgBox("Done", vbOKOnly + vbInformation)
End With
End Sub
and split
Sub SplitPOR()
Sheets("POR_IMPORT").Select
Columns("B:B").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("POR_divide").Select
Columns("A:A").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
Selection.TextToColumns Destination:=Range("A1"), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=False, _
Semicolon:=False, Comma:=False, Space:=False, Other:=True, OtherChar _
:="¦", FieldInfo:=Array(Array(1, 2), Array(2, 2), Array(3, 2), Array(4, 2), Array(5, _
2), Array(6, 2), Array(7, 2), Array(8, 2), Array(9, 2), Array(10, 2), Array(11, 2), Array(12 _
, 2), Array(13, 2), Array(14, 2), Array(15, 2), Array(16, 2), Array(17, 2), Array(18, 2), _
Array(19, 2), Array(20, 2), Array(21, 2), Array(22, 2), Array(23, 2), Array(24, 2), Array( _
25, 2), Array(26, 2), Array(27, 2), Array(28, 2), Array(29, 2), Array(30, 2), Array(31, 2), _
Array(32, 2), Array(33, 2), Array(34, 2), Array(35, 2), Array(36, 2), Array(37, 2), Array( _
38, 2), Array(39, 2), Array(40, 2), Array(41, 1), Array(42, 2), Array(43, 2), Array(44, 2), _
Array(45, 2), Array(46, 2), Array(47, 2), Array(48, 2), Array(49, 2), Array(50, 2), Array( _
51, 2), Array(52, 2), Array(53, 2), Array(54, 2), Array(55, 2), Array(56, 2), Array(57, 2), _
Array(58, 2), Array(59, 2), Array(60, 2), Array(61, 2), Array(62, 2), Array(63, 2)), _
TrailingMinusNumbers:=True
End Sub
But every time I want to repeat the process I have to close and reopen excel. The moment you insert the txt for the second time excel will automatically split it according to how it was split the first time.
Is there please any possible treatment for this case?
Apologize once more for being obtuse and not understanding what you meant!
Please, try using the next optimized solution:
Sub POR_Import()
Dim ws As Worksheet, strFile As String
Call Smaz_vstup_POR
Set ws = ActiveWorkbook.Sheets("POR_IMPORT") 'set to current worksheet name
ws.UsedRange.ClearContents 'clear the previous used range content
'Normalize the TextToColumns behavior:____________________________________________________________
With ws.Range("A1")
.value = "1,2,3"
.TextToColumns Destination:=ws.Range("A1"), DataType:=xlDelimited, ConsecutiveDelimiter:=False, Tab:=False, _
Semicolon:=False, Comma:=False, space:=False, Other:=False, FieldInfo:=Array(1, 1), TrailingMinusNumbers:=True
.ClearContents
End With
'____________________________________________________________________________________________
strFile = Application.GetOpenFilename("Text Files (*.*),*.*", , "Please select text file...")
With ws.QueryTables.Add(Connection:="TEXT;" & strFile, Destination:=ws.Range("A1"))
.TextFileParseType = xlDelimited
.TextFileTabDelimiter = True
.Refresh
End With
ws.QueryTables(ws.QueryTables.count).Delete 'delete the query after bringing the necessary text
SplitPOR ws 'call the splitting function with ws sheet as argument
MsgBox "Done", vbOKOnly + vbInformation
End Sub
Sub SplitPOR(ws As Worksheet)
Dim wsP_d As Worksheet, arrtxt(62), i As Long
Set wsP_d = Worksheets("POR_divide")
wsP_d.UsedRange.ClearContents 'clear the content, to not be ask about overwriting
wsP_d.Range("A:A").value = ws.Columns("B:B").value 'copy the column without using clipboard
For i = 0 To UBound(arrtxt) 'create the array to be passed to FieldInfo TextToColumns parameter
arrtxt(i) = Array(i + 1, 2)
Next i
'Use a more compact way:
wsP_d.Range("A:A").TextToColumns Destination:=wsP_d.Range("A1"), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=False, _
Semicolon:=False, Comma:=False, space:=False, Other:=True, OtherChar _
:="¦", FieldInfo:=arrtxt, TrailingMinusNumbers:=True
End Sub
Please, send some feedback after testing it. I will feel better knowing that I could help, after my stupid approach in comments, not being able to understand how what you were saying was possible...
I'd like to keep a cell with blank when there is no data.
Keep a cell with blank
I like to keep C3 as Empty cell like this Sample.
But My VBA gave me Sample.
Can anyone help me?
My code is:
FileToOpen = Application.GetOpenFilename(FileFilter:="Text Files(*.txt),*txt", MultiSelect:=True)
If IsArray(FileToOpen) Then
Application.ScreenUpdating = False
For i = 1 To UBound(FileToOpen)
Workbooks.OpenText _
Filename:=FileToOpen(i), _
StartRow:=1, _
DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, _
ConsecutiveDelimiter:=True, _
Tab:=True, _
Comma:=True, _
FieldInfo:=Array(Array(1, 2), Array(2, 2), Array(3, 2), Array(4, 1), _
Array(5, 2), Array(6, 2), Array(7, 2), Array(8, 2), Array(9, 2))
Set wbTextImport = ActiveWorkbook
wbTextImport.Worksheets(1).Range("A1").CurrentRegion.Copy
wsMaster.Activate
Range("A" & tgRow).Select
ActiveSheet.Paste
Application.CutCopyMode = False
wbTextImport.Close False
wsMaster.Rows(tgRow).Delete Shift:=xlUp
tgRow = wsMaster.Cells(wsMaster.Rows.Count, 1).End(xlUp).Row + 1
Next i
I am new here and want help with VBA for Excel
Each day we get some data from the system.
So i need to:
open the new file (fixed location)
Insert 3 columns & Name them
Open the old File (fixed location)
insert the formulas for each column
Apply the formula for all the rows, as in (today the new file has 20 rows, tomorrow it might have 40)
copy / paste only the values (so that the formula goes away and only the value remains)
save it under a specific name
This is the code i have so far (written with record macro since i have limited knowledge of VBA)
Sub EstrHC()
'
' EstrHC Macro
'
'
Range("A1").Select
ChDir "C:\Users\user\Desktop"
Workbooks.OpenText Filename:="C:\Users\user\Desktop\outputHC.csv", Origin _
:=xlWindows, StartRow:=1, DataType:=xlDelimited, TextQualifier:= _
xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=True, Semicolon:=False, _
Comma:=False, Space:=False, Other:=False, FieldInfo:=Array(Array(1, 1), _
Array(2, 1), Array(3, 1), Array(4, 1), Array(5, 1), Array(6, 1), Array(7, 1), Array(8, 1), _
Array(9, 1), Array(10, 1), Array(11, 1), Array(12, 1), Array(13, 1), Array(14, 1), Array(15 _
, 1), Array(16, 1), Array(17, 1), Array(18, 1), Array(19, 1), Array(20, 1), Array(21, 1), _
Array(22, 1), Array(23, 1), Array(24, 1), Array(25, 1), Array(26, 1), Array(27, 1), Array( _
28, 1), Array(29, 1), Array(30, 1), Array(31, 1), Array(32, 1), Array(33, 1), Array(34, 1), _
Array(35, 1), Array(36, 1), Array(37, 1), Array(38, 1), Array(39, 1), Array(40, 1), Array( _
41, 1), Array(42, 1), Array(43, 1), Array(44, 1), Array(45, 1), Array(46, 1), Array(47, 1), _
Array(48, 1), Array(49, 1), Array(50, 1), Array(51, 1)), TrailingMinusNumbers:=True
Columns("F:F").Select
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
Columns("F:F").Select
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
Range("F1").Select
ActiveCell.FormulaR1C1 = "Assegnato"
Range("G1").Select
ActiveCell.FormulaR1C1 = "Esito"
Range("H1").Select
ActiveCell.FormulaR1C1 = "Note"
Range("F1:H1").Select
With Selection.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.ThemeColor = xlThemeColorLight2
.TintAndShade = 0.799981688894314
.PatternTintAndShade = 0
End With
Columns("E:E").ColumnWidth = 14.43
Columns("F:F").ColumnWidth = 13.57
Range("F2").Select
ChDir "C:\Users\user\Desktop\Estr\HC"
Workbooks.Open Filename:="C:\Users\user\Desktop\Estr\HC\HC.xlsx"
Windows("outputHC.csv").Activate
ActiveCell.FormulaR1C1 = _
"=VLOOKUP(RC[-1],'[HC.xlsx]20200604 Rds da gestire'!C5:C6,2,0)"
Range("G2").Select
ActiveCell.FormulaR1C1 = _
"=VLOOKUP(RC[-2],'[HC.xlsx]20200604 Rds da gestire'!C5:C7,3,0)"
Range("H2").Select
ActiveCell.FormulaR1C1 = _
"=VLOOKUP(RC[-3],'[HC.xlsx]20200604 Rds da gestire'!C5:C8,4,0)"
Range("F2:H2").Select
Selection.AutoFill Destination:=Range("F2:H15")
Range("F2:H15").Select
Selection.Copy
Application.CutCopyMode = False
Range("F1:H1").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Range("H8").Select
Application.CutCopyMode = False
With ActiveWorkbook
.KeepChangeHistory = True
.ChangeHistoryDuration = 30
End With
ActiveWorkbook.SaveAs Filename:= _
"C:\Users\user\Desktop\2020 Rds da gestire.xlsx", FileFormat:= _
xlOpenXMLWorkbook, AccessMode:=xlShared
Windows("Cartel1.xlsx").Activate
End Sub
Thank you
My recorded macro errs sometimes because the file is open already (See macro below).
Can somebody tell me how to change the macro to first check if the Excel worksheet (Volledige Ice export.xlsx) is open, and if it is open, close the file first? With regards to the latter, I see I can do that with:
Windows("Volledige Ice export.xlsx").Activate
ActiveWorkbook.Close
The full macro:
Sub Ice()
Workbooks.OpenText Filename:="C:\Users\Doe\Documents\Ice\export.txt", _
Origin:=xlMSDOS, StartRow:=1, DataType:=xlDelimited, TextQualifier:= _
xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=True, Semicolon:=False, _
Comma:=False, Space:=False, Other:=False, FieldInfo:=Array(Array(1, 2), _
Array(2, 2), Array(3, 2), Array(4, 2), Array(5, 2), Array(6, 2), Array(7, 9), Array(8, 9), _
Array(9, 2), Array(10, 1), Array(11, 9), Array(12, 1), Array(13, 9), Array(14, 9), Array(15 _
, 9), Array(16, 9), Array(17, 9), Array(18, 9), Array(19, 9), Array(20, 9), Array(21, 2), _
Array(22, 9), Array(23, 9), Array(24, 2), Array(25, 2)), DecimalSeparator:=".", _
ThousandsSeparator:=",", TrailingMinusNumbers:=True
Windows("Ice_macro.xlsm").Activate
Windows("export.txt").Activate
Columns("A:B").Select
Selection.ColumnWidth = 21
Columns("D:D").Select
Selection.ColumnWidth = 18
Columns("E:E").Select
Selection.ColumnWidth = 15
Columns("F:F").Select
Selection.ColumnWidth = 60
Columns("G:G").Select
Selection.ColumnWidth = 45
Columns("H:H").Select
Selection.ColumnWidth = 12
Columns("L:L").Select
Selection.ColumnWidth = 45
Columns("G:G").Select
With Selection.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 65535
.TintAndShade = 0
.PatternTintAndShade = 0
End With
Range("A1").Select
Selection.AutoFilter
ActiveWorkbook.SaveAs Filename:= _
"C:\Users\Doe\Documents\Ice\Volledige Ice export.xlsx", FileFormat _
:=xlOpenXMLWorkbook, CreateBackup:=False
ActiveWorkbook.Close
End Sub
Below you'll find possible solution, together with Chronocidal's comment implementation. You should compare your recorded code to this to understand it.
In short, Chronocidal means that this:
Columns("H:H").Select
Selection.ColumnWidth = 12
is the same as this:
Columns("H:H").ColumnWidth = 12
but second version is a lot more efficient.
The code:
Sub Ice()
Dim wsExport As Worksheet
Dim wbIce As Workbook
' try to assign workbook to variable
On Error Resume Next
' in case wb is closed - there will be an error
Set wbIce = Workbooks("Volledige Ice export")
On Error GoTo 0
' if wb is open it will be assigned to variable
If Not wbIce Is Nothing Then
' close without saving
wbIce.Close False
End If
Workbooks.OpenText fileName:="C:\Users\Doe\Documents\Ice\export.txt", _
Origin:=xlMSDOS, StartRow:=1, DataType:=xlDelimited, TextQualifier:= _
xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=True, Semicolon:=False, _
Comma:=False, Space:=False, Other:=False, FieldInfo:=Array(Array(1, 2), _
Array(2, 2), Array(3, 2), Array(4, 2), Array(5, 2), Array(6, 2), Array(7, 9), Array(8, 9), _
Array(9, 2), Array(10, 1), Array(11, 9), Array(12, 1), Array(13, 9), Array(14, 9), Array(15 _
, 9), Array(16, 9), Array(17, 9), Array(18, 9), Array(19, 9), Array(20, 9), Array(21, 2), _
Array(22, 9), Array(23, 9), Array(24, 2), Array(25, 2)), DecimalSeparator:=".", _
ThousandsSeparator:=",", TrailingMinusNumbers:=True
Set wsExport = ActiveSheet
With wsExport
.Columns("A:B").ColumnWidth = 21
.Columns("D:D").ColumnWidth = 18
.Columns("E:E").ColumnWidth = 15
.Columns("F:F").ColumnWidth = 60
.Columns("G:G").ColumnWidth = 45
.Columns("H:H").ColumnWidth = 12
.Columns("L:L").ColumnWidth = 45
With .Columns("G:G").Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 65535
.TintAndShade = 0
.PatternTintAndShade = 0
End With
.Cells("A1").AutoFilter
End With
With wsExport.Parent
.SaveAs fileName:= _
"C:\Users\Doe\Documents\Ice\Volledige Ice export.xlsx", FileFormat _
:=xlOpenXMLWorkbook, CreateBackup:=False
.Close
End With
End Sub
I have converted a macro enabled document I have from XLSM to an XLSB as this was created in Excel 2010 but users have now moved to Excel 2016.
I have come across an issue when I copy information containing delimitation characters from a Notepad e.g. text; 1; 2; 3 and paste this into the Excel: it delimits itself into multiple columns but I need it to stay in the un-delimited format.
Is there anyway to go about this? the only way so far I have found to do this is to copy it to another Excel sheet first but this isn't practical.
Selection.TextToColumns Destination:=Range("C2"), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=False, _
Semicolon:=True, Comma:=False, Space:=False, Other:=True, OtherChar _
:=":", FieldInfo:=Array(Array(1, 1), Array(2, 1), Array(3, 1), Array(4, 1), Array(5, _
1), Array(6, 1), Array(7, 1), Array(8, 1), Array(9, 1), Array(10, 1), Array(11, 1), Array(12 _
, 1), Array(13, 1), Array(14, 1), Array(15, 1), Array(16, 1), Array(17, 1), Array(18, 1), _
Array(19, 1), Array(20, 1), Array(21, 1), Array(22, 1), Array(23, 1), Array(24, 1), Array( _
25, 1), Array(26, 1), Array(27, 1), Array(28, 1), Array(29, 1)), TrailingMinusNumbers _
:=True
Columns("C:AD").Select
Columns("C:AD").EntireColumn.AutoFit
Columns("G:G").Select
Selection.Delete Shift:=xlToLeft
Columns("E:E").Select
Columns("E:E").Cut Destination:=Columns("H:H")
Columns("E:E").Select
Selection.Delete Shift:=xlToLeft
Columns("J:J").Select
Range("J:J,L:Y,AA:AB").Select
Range("AA1").Activate
Selection.Delete Shift:=xlToLeft
ActiveWindow.ScrollColumn = 1
Range("A1").Select
You could fake a the text to column to clear its options
Sub ClearTextToColumns()
If IsEmpty(Range("A1")) Then Range("A1") = "XXXX"
Range("A1").TextToColumns Destination:=Range("A1"), _
DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, _
ConsecutiveDelimiter:=False, _
Tab:=False, _
Semicolon:=False, _
Comma:=False, _
Space:=False, _
Other:=False, _
OtherChar:=""
If Range("A1") = "XXXX" Then Range("A1") = ""
End Sub
Note that the contents of cell A1 will not be modified because no operations are specified for the TextToColumns method.
Note that the second part of your code can be reduced to
Columns("C:AD").EntireColumn.AutoFit
Columns("G:G").Delete Shift:=xlToLeft
Columns("E:E").Cut Destination:=Columns("H:H")
Columns("E:E").Delete Shift:=xlToLeft
Range("J:J,L:Y,AA:AB").Delete Shift:=xlToLeft
Using .Select is a bad practice and not necessary to do these actions. If you avoid that your code gets much more stable, faster and prevents many issues.
Also see: How to avoid using Select in Excel VBA.