I am trying to select all the data in a column and make it proper case.
This is what I'm starting with:
Range("D3").Select
Range(Selection, Selection.End(xlDown)).Select
I think I want to use Application.WorksheetFunction.Proper.
Here is my approach to this, adjust the column index (rw.Row, 1) to suit your project
Sub ConvertValuesInColumnOneToProperCase()
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet: Set ws = ActiveSheet
Dim rw As Range
For Each rw In ws.UsedRange.Rows
ws.Cells(rw.Row, 1) = StrConv(ws.Cells(rw.Row, 1), vbProperCase)
Next rw
End Sub
Please, try this way. The next code processes the values in column E:E. You can easily adapt it for another column. No need to select anything. Selecting, activating only consumes Excel resources without bringing any benefit:
Sub UcaseRange()
Dim sh As Worksheet, rng As Range
Set sh = ActiveSheet
Set rng = sh.Range("E2:E" & sh.Range("E" & sh.rows.count).End(xlUp).row)
rng = Evaluate("INDEX(UPPER(" & rng.Address(0, 0) & "),)")
End Sub
Related
I'm wanting to use VBA to copy a range of data from one workbook and paste it in another workbook. To know where to paste the information, I search for the next empty row.
The code works successfully until the last portion when trying to copypaste values. I do not get any errors, or any indication of success or failure. I can see it being copied correctly (the marching dots), and the correct cell is selected, but nothing is pasted.
Sub Button1_Click()
Dim wb1 As Workbook
Dim sht As Worksheet
Dim rng As Range
Dim databasewb As Workbook
Dim databasesht As Worksheet
Dim eRow As Integer
'set workbooks to variables
Set databasewb = Workbooks("Aged Debt Data V1.xlsm")
Set wb1 = Workbooks.Open("C:\Users\roanderson\Desktop\Aged debt\Templates\BIO Inc (IO) Template.xlsx")
'select sheet where data lies
Set sht = wb1.Sheets("Conversion to aged debt format")
sht.Activate
'copy range on sheet
Set rng = sht.Range("A2", Range("A2").End(xlDown).End(xlToRight))
rng.Copy
' paste range into database
'activate database workbook
databasewb.Activate
'find next empty row
eRow = Sheet1.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
MsgBox (eRow)
'paste values into empty row
Sheet1.Cells(eRow, 1).Select
rng.PasteSpecial Paste:=xlPasteValues
wb1.Close
End Sub
The data to be pasted in the Datebase workbook,
When possible, try to avoid using Copy Paste with VBA, as well as avoid using select. Since you just want to copy values, using VBA's Value approach would likely be easier. Modify your line of code where you try to paste special to setting the value. See below
'paste values into empty row
Sheet1.Cells(eRow, 1).Resize(RNG.Rows.Count, RNG.Columns.Count).Value = RNG.Value
wb1.Close
What this is doing starting in Cells(erow,1) the code is using Resize to set the starting range to be the same number of rows and columns or your variable RNG. Then it's just setting the values, the same result as CopyPasteValue only less overhead.
However, if you did want to keep the approach of Copy paste value, then modify your code as such:
'paste values into empty row
Sheet1.Cells(eRow, 1).PasteSpecial Paste:=xlPasteValues
wb1.Close
Change rng.pastespecial to
selection.pastespecial
Performance improvement for copy-paste values. Modular sub.
Bypassing the clipboard is recommended for just Pasting Values. PasteSpecial is less efficient.
See section 8: https://techcommunity.microsoft.com/t5/excel/9-quick-tips-to-improve-your-vba-macro-performance/m-p/173687
Sub CopyPasteSingleCol pastes to PasteFirstRow for Single Column.
sub CopyPasteSingleCol2firstBlank pastes after last blank in column for Single Column.
Sub CopyPasteSingleCol(SrcSheet As Worksheet, ByVal SrcCol As String, ByVal SrcFirstRow As Long, _
PasteSheet As Worksheet, ByVal PasteCol As String, ByVal PasteFirstRow As Long)
Dim SrcLastRow As Long
Dim PasteLastrow As Long
Dim SrcRng As Range
Dim PasteRng As Range
SrcLastRow = SrcSheet.Cells(SrcSheet.Rows.Count, SrcCol).End(xlUp).Row
Set SrcRng = SrcSheet.Range(SrcCol & SrcFirstRow & ":" & SrcCol & SrcLastRow)
Set PasteRng = PasteSheet.Range(PasteCol & PasteFirstRow)
SrcRng.Copy PasteRng
End Sub
Sub CopyPasteSingleCol2firstBlank(SrcSheet As Worksheet, ByVal SrcCol As String, ByVal SrcFirstRow As Long, _
PasteSheet As Worksheet, ByVal PasteCol As String)
Dim SrcLastRow As Long
Dim PasteLastrow As Long
Dim SrcRng As Range
Dim PasteRng As Range
SrcLastRow = SrcSheet.Cells(SrcSheet.Rows.Count, SrcCol).End(xlUp).Row
PasteLastrow = PasteSheet.Cells(PasteSheet.Rows.Count, PasteCol).End(xlUp).Row + 1
' If first row is empty there was not need to add +1 to Lastrow
If PasteSheet.Cells(1, PasteCol) = vbNullString Then PasteLastrow = 1
Set SrcRng = SrcSheet.Range(SrcCol & SrcFirstRow & ":" & SrcCol & SrcLastRow)
Set PasteRng = PasteSheet.Range(PasteCol & PasteLastrow)
SrcRng.Copy PasteRng
End Sub
Sub TESTCopyPasteSingleCol()
Dim SrcSheet As Worksheet
Dim PasteSheet As Worksheet
'Must qualify your Sheet by using Set before calling sub
Set SrcSheet = Workbooks("importGsheettoExcel3.xlsm").Worksheets("SH1")
Set PasteSheet = Workbooks("importGsheettoExcel.xlsm").Worksheets("SH2")
Call CopyPasteSingleCol(SrcSheet, "B", 2, _
PasteSheet, "G", 2)
End Sub
Sub TESTCopyPasteSingleCol2firstBlank()
Dim SrcSheet As Worksheet
Dim PasteSheet As Worksheet
'Must qualify your Sheet by using Set before calling sub
Set SrcSheet = Workbooks("importGsheettoExcel3.xlsm").Worksheets("SH1")
Set PasteSheet = Workbooks("importGsheettoExcel.xlsm").Worksheets("SH2")
Call CopyPasteSingleCol2firstBlank(SrcSheet, "B", 2, _
PasteSheet, "G")
End Sub
Update: I realized that I can't use union on multiple sheets.
What's the best choice that I have then?
I simply want to combine all sheets in the workbook into the first worksheet.
After I went through the existing questions, I've tried adding Set rng = nothing to clear my range, but it didn't help.
Sub Combine()
Dim J As Long
Dim Combine As Range
Dim rng As Range
'I want to start from the second sheet and go through all of them
For J = 2 To Sheets.Count
With Sheets(J)
Set rng = .Range("A1", .Range("A" & .Rows.Count).End(xlUp))
End With
For Each Cell In rng
If Combine Is Nothing Then
Set Combine = Cell.EntireRow
Else
Set Combine = Union(Combine, Cell.EntireRow)
End If
Next Cell
Set rng = Nothing
Next J
'Paste the whole union into the 1st sheet
Combine.Copy Destination:=Sheets(1).Range("A1")
End Sub
All this code gets me an error Method 'Union' of object '_Global failed
Update 2
Sub Combine2()
Dim rowcount As Long
For Each Sheet In Sheets
If Sheet.Index <> 1 Then
rowcount = Sheet.UsedRange.Rows.Count
Sheet.UsedRange.Copy Destination:=Sheets(1).Cells(Lastrow + 1, 1)
Lastrow = Lastrow + rowcount
End If
Next Sheet
End Sub
Really simple code, worked perfectly, thanks to #luuklag for leading me on this.
Indeed .Union method doesn't work across worksheets.
Instead, you could try looping through all your worksheets, copying the corresponding range and pasting it to the destination worksheet.
Something like the following would achieve this:
Sub test()
Dim destinationSheet As Worksheet
Dim sht As Worksheet
Dim destinationRng As Range
Dim rng As Range
Set destinationSheet = ThisWorkbook.Worksheets("Name of your worksheet")
For Each sht In ThisWorkbook.Worksheets
If sht.Name <> destinationSheet.Name Then
With sht
Set rng = .Range(.Range("A1"), .Range("A" & .Rows.Count).End(xlUp))
rng.Copy
End With
With destinationSheet
Set destinationRng = .Range("A" & .Rows.Count).End(xlUp)
If destinationRng.Address = .Range("A1").Address Then
destinationRng.PasteSpecial xlPasteValues
Else
destinationRng.Offset(1, 0).PasteSpecial xlPasteValues
End If
End With
End If
Next sht
End Sub
The code above pastes the ranges one by one, in the same column. It can be easily modified to paste the ranges in different columns, one next to the other.
I have a code that should restore range formatting after applying few step.
Sub MyCode()
Sheets("My sheet").ListObjects("My Table").DataBodyRange.Copy
...
refreshing connection and calling function that applies stored formulas to table columns
...
Sheets("My sheet").[A10].PasteSpecial Paste:=xlPasteFormats
End sub
I got error PasteSpecial method on range failed
If I paste immediately, it works.
Is it possible to save range formatting as variable?
Here is an example on how to use variables to store the copy method and use it later. You can set the range to a variable CopyRange and use CopyRange.Copy to store it and later you can use it as the range was stored in the CopyRange and not lost along the way due to other processes running down the line.
Option Explicit
Sub CopyDataToTemplate()
Dim ws As Worksheet
Dim srcWB As Workbook
Dim destWB As Workbook
Dim srcWS As Worksheet
Dim destWS As Worksheet
Dim CopyRange As Variant
Dim i As Long, j As Long
Dim srcLRow As Long, destLRow As Long
Set destWB = Excel.Workbooks("DOLine_example.xlsx")
Set srcWB = ActiveWorkbook
Set srcWS = srcWB.ActiveSheet
Set destWS = destWB.Sheets("DOLine")
srcLRow = srcWS.Cells(srcWS.Rows.Count, "A").End(xlUp).Row
destLRow = destWS.Cells(destWS.Rows.Count, "A").End(xlUp).Row
Application.ScreenUpdating = False
'loop through column 1 to 19
For i = 1 To 19
For j = 1 To 13
'loop through columns
If destWS.Cells(3, i).value = srcWS.Cells(1, j).value Then
' Copy column B to Column D as written in your code above
Set CopyRange = srcWS.Range(Cells(2, j), Cells(srcLRow, j))
CopyRange.Copy
' paste columns from one wb to Columns to another wb
destWS.Cells(destLRow, i).PasteSpecial Paste:=xlPasteAll, Transpose:=False
Application.CutCopyMode = False
End If
Next j
Next i
Application.ScreenUpdating = True
MsgBox "Process completed!", vbInformation
End Sub
I currently have a macro that copies data from one sheet and archives it in another sheet. The issue that I have is that it is copying and pasting the formulas and it need to copy and paste values only.
Sub Archive_Execution()
Dim mainworkbook As Workbook
Set mainworkbook = ActiveWorkbook
Dim rangeName
Dim strDataRange As Range
Dim keyRange As Range
rangeName = "Archive_Execution"
Application.Goto Reference:=rangeName
Selection.Copy
Sheets("Archive Execution").Activate
Range("A" & Rows.Count).End(xlUp).Offset(1).Select
mainworkbook.Sheets("Archive Execution").Paste
Sheets("Archive Execution").Activate
Set strDataRange = Range("A2:AA1000000")
Set keyRange = Range("D1")
strDataRange.Sort Key1:=keyRange, Order1:=xlAscending
End Sub
Any help would be greatly appreciated on tweaking my code so that only values are pasted not formulas
As mentioned in comments use Range().PasteSpecial xlPasteValues if you want to copy only values.
I also recommend using the Intersect method and Worksheets("").UsedRange to trim down your ranges.
Sub Archive_Execution()
Dim strDataRange As Range
Dim keyRange As Range
With Sheets("Archive Execution")
Range("Archive_Execution").Copy
.Range("A" & Rows.Count).End(xlUp).Offset(1).PasteSpecial xlPasteValues
End With
With Sheets("Archive Execution")
Set strDataRange = Intersect(.Range("A2:AA" & .Rows.Count), .UsedRange)
Set keyRange = .Range("D1")
strDataRange.Sort Key1:=keyRange, Order1:=xlAscending
End With
End Sub
To avoid using Copy and Paste you can try something like the following, much faster than copy pasting.
Sub Archive_Execution()
Dim mainworkbook As Workbook, rangeName
Dim strDataRange As Range, keyRange As Range
Dim r As Integer, c As Integer
Set mainworkbook = ActiveWorkbook
rangeName = "Archive_Execution"
r = Range(rangeName).Rows.Count
c = Range(rangeName).Columns.Count
With Sheets("Archive Execution").Range("A" & Rows.Count).End(xlUp).Offset(1)
.Resize(r, c) = Range(rangeName).Value
End With
Sheets("Archive Execution").Activate
Set strDataRange = Range("A2:AA1000000")
Set keyRange = Range("D1")
strDataRange.Sort Key1:=keyRange, Order1:=xlAscending
End Sub
i need to rename all my sheets dynamically based on a range of cell values.
This is my VBA codes, it keeps giving me a 'Runtime Error '1004 whenever i run it.
Sub RenameSheets()
Dim MyCell As Range, MyRange As Range
Set MyRange = Sheets("Config").Range("A5")
Set MyRange = Range(MyRange, MyRange.End(xlDown))
Sheets("Sheet1").Activate
For Each MyCell In MyRange
ActiveSheet.Name = MyCell.Value 'Error here. it works fine if i rename MyCell.Value to "AnyRandomValue"
Worksheets(ActiveSheet.Index + 1).Select
Next MyCell
End Sub
I cant get my head around it. Why is it giving an error at MyCell.Value? Please help!
The problem I think is activating the sheets your working on by .Select method.
Avoid using select as much as possible. Check out the link.
Your code can be rewritten like below:
Sub RenameSheets()
Dim MyNames As Variant
MyRange As Range, ws As Worksheet
Dim i As Long
With Sheets("Config")
Set MyRange = .Range("A5", .Range("A" & _
.Rows.Count).End(xlUp).Address)
'~~> pass names to array
MyNames = Application.Transpose(MyRange)
i = Lbound(MyNames)
End With
'~~> iterate sheets instead
For Each ws In Worksheets
If ws.Name <> "Config" Then
ws.Name = MyNames(i) '~~> retrieve from array
i = i + 1
End If
Next ws
End Sub
Is this what you're trying?