Paste Special code - excel

Public Sub CopyPaste()
Dim j As Long
For j = 2 To 52
Range("AE" & j).Select
Selection.Copy
Range("AE" & j).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
Range("AF" & j).Select
Selection.Copy
Range("AF" & j).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
Range("AG" & j).Select
Selection.Copy
Range("AG" & j).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
Application.CutCopyMode = False
End If
Next j
End Sub
Is there any way to minimize this code. I have tried using Range("AE:AG" & j).Select, but it showing some error.

Yes, it is.
If you want to paste only values you can equals ranges values. But you need to use cells and exact sheet object. For example
Public Sub CopyPaste()
Dim ws As Worksheet
Set ws = ActiveSheet
ws.Range(ws.Cells(2, 31), ws.Cells(52, 34)).Values = _
ws.Range(ws.Cells(2, 31), ws.Cells(52, 34)).Values
Set ws = Nothing
End Sub

It's always best to avoid using Select, Copy and Paste. You can almost always use .Value = ... in their place.
Assuming this is what you want to do (it isn't too clear from your question), if you ever want to replace a formulated cell with its value you can just set its value to itself:
Sub RemoveFormulas()
With ActiveSheet
.Range(.Cells(2, 31), .Cells(52, 34)).Value = _
.Range(.Cells(2, 31), .Cells(52, 34)).Value
End With
End Sub

Related

How do I create a macro that will run a formula loan by loan, and paste the output in a separate sheet

I'm setting up a pricing model and am wondering how I am able to get the macro to run the pricing loan by loan and have the output pasted in a separate tab (this would also be loan by loan, so it cannot overwrite). I used the macro recorder and this is what I have so far, but I'm a novice and not sure how to loop this until it hits a blank cell (I did the first two loans....)
Sub Macro1()
'
' Macro1 Macro
'
'
Selection.Copy
Sheets("Cashflows").Select
Range("A3").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Range(Selection, Selection.End(xlToRight)).Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Output").Select
Range("A2").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Sheets("Input").Select
Range("A3").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Cashflows").Select
Range("A3").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Range(Selection, Selection.End(xlToRight)).Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Output").Select
Range("A3").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
End Sub
The tools you need:
To figure out the last row:
Dim LastRow As Integer
LastRow = Range("A" & Rows.Count).End(xlUp).Row
'This simulates selecting the last cell in "A" Column,
'hitting "End" and "Up Arrow", then returns that row number
'as in integer.
To cycle through each row:
Dim I As Integer
For I = 1 To 10 '(Or replace "10" with "LastRow")
'Do something like look at a range value:
Debug.Print Cells(I, 1).Value
Next I
Finally, this is going to be a lot easier if you use .value = .value instead of copying and pasting:
Dim RowNum As Integer
RowNum = 10
Range("A1").Value = Range("B1").Value 'Copies Value from B1 into A1
Cells(1, 1).Value = Range("B1").Value 'Does Exact same thing as above: Cells(row, column)
'Copy A10:C10 from sheet2 to sheet1:
Sheet1.Range("A" & RowNum & ":C" & RowNum).Value = Sheet2.Range("A" & RowNum & ":C" & RowNum)
See how far you get with that and come back if you have more specific questions.
There are lots of good resources out there if you're having trouble.

How to use a variable in the address of the Range method

How can I set variable in Range? This is my code:
Sub Makro1()
Dim value As String
ThisWorkbook.Sheets("Arkusz1").Activate
ThisWorkbook.Sheets("Arkusz1").Range("R3").Select
value = ThisWorkbook.Sheets("Arkusz1").Range("R3").value
ThisWorkbook.Worksheets("Arkusz1").Range("C:value").Select '<--- Here is the BUG
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
End Sub
For ranges the format is:
startColumn & StartRow & ":" & EndColumn & EndRow
EndColumn and EndRow are optional is not specified then they will be the same as Startcolumn and StartRow
for example to reference a range from column A, row 1 to Column D, Row 20 use:
sAddress = "A1:D20"
Untested
Consider:
Sub Makro1()
Dim valuee As String
ThisWorkbook.Sheets("Arkusz1").Activate
ThisWorkbook.Sheets("Arkusz1").Range("R3").Select
valuee = ThisWorkbook.Sheets("Arkusz1").Range("R3").value
ThisWorkbook.Worksheets("Arkusz1").Range("C" & valuee).Select
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
End Sub

How to repeat code to apply merged cell formatting to multiple rows?

I'm creating a button that will allow the user to add a new record to the very top of the list, and move all records one row below (to keep the newest records at the top). The code I've written works perfectly as-is. However, I have to write a lot of repeating code to apply it to all rows within the range. Here is my code:
Sub Test2()
' Stop screen from following macro actions & disable alerts
Application.ScreenUpdating = False
Application.DisplayAlerts = False
' If more than 1 record, copy all rows and paste 1 row below, apply merged cell formatting, clear data from first row, and re-enable alerts/screen updating
If WorksheetFunction.CountA(Range("AM5:AN21")) > 1 Then
Range("CW28:DJ28").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
Range("CW29:DJ29").Select
ActiveSheet.Paste
Range("CW28:DJ28").Select
Selection.Copy
Range("CW29").Select
Selection.PasteSpecial Paste:=xlPasteFormats, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=False
...
Range("CW1277").Select
Selection.PasteSpecial Paste:=xlPasteFormats, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=False
Application.CutCopyMode = False
Range("CW28:DJ28").Select
Selection.ClearContents
Range("CW28:CX28").Select
Application.DisplayAlerts = True
Application.ScreenUpdating = True
' If only 1 record, copy first row and paste 1 row below, apply merged cell formatting, clear data from first row, and re-enable alerts/screen updating
ElseIf WorksheetFunction.CountA(Range("AM5:AN21")) = 1 Then
Range("CW28:DJ28").Select
Selection.Copy
Range("CW29:DJ29").Select
ActiveSheet.Paste
Range("CW28:DJ28").Select
Selection.Copy
Range("CW29").Select
Selection.PasteSpecial Paste:=xlPasteFormats, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=False
...
Range("CW1277").Select
Selection.PasteSpecial Paste:=xlPasteFormats, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=False
Application.CutCopyMode = False
Range("CW28:DJ28").Select
Selection.ClearContents
Range("CW28:CX28").Select
Application.DisplayAlerts = True
Application.ScreenUpdating = True
' If zero records, re-enable alerts/screen updating
Else
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End If
End Sub
As you can see, the two spots where the "..." I need to apply to rows 29 through 1277. I know there's got to be a better way to do this with For ... Next, but what I've tried hasn't worked (code that I used is below, it would give me an error saying I can't do that to merged cells, even though my current code works).
Dim rng As Range: Set rng = Application.Range("CW28:CX1277")
Dim i As Integer
For i = 1 To 1248
rng.Cells(RowIndex:=i, ColumnIndex:="CW").Select
Selection.PasteSpecial Paste:=xlPasteFormats, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=False
Next
I know my entire issue is that we have merged cells, but we need to keep them if at all possible. Knowing that my current, repetitive coding works... is there a way to make the For ... Next function work?
What I understand of your code is that you copy the format of line N to line N+1 for columns CW to DJ, from lines 28 to 1277, by block.
(I strongly suppose it is not as much simple).
What you could do is (I replace your 28 by beginRow) :
dim beginRow as long, endRow as long
dim strRange as string
beginRow=28
while (beginRow<<1277)
strRange = "CW" & beginRow & ":DJ" & beginRow
Range(strRange).select
endRow=Selection.End(xlDown).row
strRange = "CW" & beginRow & ":DJ" & endRow
Range(strRange).Copy
strRange = "CW" & (beginRow+1) & ":DJ" & (endRow+1)
Range(strRange).Select
ActiveSheet.Paste
strRange = "CW" & (beginRow) & ":DJ" & (beginRow+1)
Range(strRange).Copy
Range("CW" & (beginRow+1)).Select
Selection.PasteSpecial Paste:=xlPasteFormats, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=False
' find next block
beginRow=Range("CW" & (endRow+1)).End(xlDown).row
wend
Could this help ?
Pierre.
I figured it out!
Dim rng As Range
Dim cell As Range
Range("CW28:DJ28").Select
Selection.Copy
Set rng = Range("CW29:1277")
For Each cell In rng.Cells
cell.Select
Selection.PasteSpecial Paste:=xlPasteFormats, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=False
Next cell
Application.CutCopyMode = False
Now, I need to focus on how to get rid of .Select and .Activate throughout my code. Thank you so much for your help, all!

How to convert Excel VBA created on a mac to Windows?

I've made a VBA for a button in Excel for Mac that is supposed to copy the content of a few selected cells on one tab and paste it (as values) on the first available cell in an assigned row on a different tab.
This is the first time I've ever had a go at making this, so I probably didn't do it as efficient as possible, but it works.
The problem is that it only works on Mac. My co-workers that I've made it for uses PC. Can I convert the code to work on Excel for PC?
Edit: I should have been more explicit into what the problem actually is (thanks #KenWhite).
So here's what happened:
I created the file and the VBA.
I saved my file and attatched it to an email
my co-worker saved it and opened it up
When she pressed the button she got an error "Indexet är utanför intervall". My best translation for this is Index out of Range (but I'm not completely sure)
I suspected that it had to do with Mac -> PC, but some have pointed out that there should be no difference. I realize that the named on the sheets and that the data needs to be in the exact same spot - but that shouldn't be an issue in this case.
Edit 2: It seems to be a problem with special characters. the "ä" and "ö" used in the sheet names where changed in to "š" and "¨" in the VBA code on their end. I can't test it right now, but my guess is that the code will work if I either manually change the characters in the code or make sure to use sheet names without special characters.
If I should/could add additional information, let me know and I'll make another edit.
Thank you everyone.
Sub Generera()
'
' Generera Makro
'
'
Range("B1").Select
Selection.Copy
Sheets("Utveckling över tid").Select
BMaxRows = Cells(Rows.Count, "B").End(xlUp).Row
Range("B" & BMaxRows + 1).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Sheets("veckoräckvidd").Select
Range("B2").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Utveckling över tid").Select
CMaxRows = Cells(Rows.Count, "C").End(xlUp).Row
Range("C" & CMaxRows + 1).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Sheets("veckoräckvidd").Select
Range("B3").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Utveckling över tid").Select
DMaxRows = Cells(Rows.Count, "D").End(xlUp).Row
Range("D" & DMaxRows + 1).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Sheets("veckoräckvidd").Select
Range("B4").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Utveckling över tid").Select
EMaxRows = Cells(Rows.Count, "E").End(xlUp).Row
Range("E" & EMaxRows + 1).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Sheets("veckoräckvidd").Select
Range("B6").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Utveckling över tid").Select
FMaxRows = Cells(Rows.Count, "F").End(xlUp).Row
Range("F" & FMaxRows + 1).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Sheets("veckoräckvidd").Select
Range("B7").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Utveckling över tid").Select
GMaxRows = Cells(Rows.Count, "G").End(xlUp).Row
Range("G" & GMaxRows + 1).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Sheets("veckoräckvidd").Select
Range("B8").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Utveckling över tid").Select
HMaxRows = Cells(Rows.Count, "H").End(xlUp).Row
Range("H" & HMaxRows + 1).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Sheets("veckoräckvidd").Select
Range("B9").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("veckoräckvidd").Select
Range("B11").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Utveckling över tid").Select
IMaxRows = Cells(Rows.Count, "I").End(xlUp).Row
Range("I" & IMaxRows + 1).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Sheets("veckoräckvidd").Select
Range("B12").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Utveckling över tid").Select
JMaxRows = Cells(Rows.Count, "J").End(xlUp).Row
Range("J" & JMaxRows + 1).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
End Sub
I believe this is a replacement for your current macro, so this might solve your problem.
Sub Generera()
Dim ws1 As Worksheet
Set ws1 = sheets("Utveckling över tid")
Dim ws2 As Worksheet
Set ws2 = sheets("veckoräckvidd")
Dim i As Long
For i = 2 To 10
Dim colLetter As String
colLetter = Split(Cells(1, i).Address, "$")(1)
ws1.Range(colLetter & ws1.Cells(rows.count, colLetter).End(xlUp).row + 1).value = ws2.Range("B" & i - 1).value
Next i
End Sub
Here are the steps I took to convert your original code to my shorter version:
Range("B1").Select
Selection.copy
sheets("Utveckling över tid").Select
BMaxRows = Cells(rows.count, "B").End(xlUp).row
Range("B" & BMaxRows + 1).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
Stopped using .Select, and started using direct Range().value transferring instead of .copy and .pastespecial so that I dont have to juggle cutcopymode and because you're not doing anything special, just copying the values only.
BMaxRows = sheets("veckoräckvidd").Cells(rows.count, "B").End(xlUp).row
sheets("veckoräckvidd").Range("B" & BMaxRows + 1).value = _
sheets("Utveckling över tid").Range("B1").value
Include the statement for BMaxRows inside of the range itself for eventual simplicity.
sheets("veckoräckvidd").Range("B" & sheets("veckoräckvidd").Cells(rows.count, "B").End(xlUp).row + 1).value = _
sheets("Utveckling över tid").Range("B1").value
Use Worksheet variables to shorten every time that I need to refer to one of the sheet names.
ws2.Range("B" & ws2.Cells(rows.count, "B").End(xlUp).row + 1).value = _
ws1.Range("B1").value
And to convert it to a loop you can compare a couple of the converted operations side by side to see what changes every instance. In this case it's the column letter for ws2 and the row number in ws1.
ws2.Range("B" & ws2.Cells(rows.count, "B").End(xlUp).row + 1).value = ws1.Range("B1").value
ws2.Range("C" & ws2.Cells(rows.count, "C").End(xlUp).row + 1).value = ws1.Range("B2").value
ws2.Range("D" & ws2.Cells(rows.count, "D").End(xlUp).row + 1).value = ws1.Range("B3").value

Excel Macro copying poorly formatted data into table

I have been tasked with extracting data out of an Excel sheet that is strangely/poorly formatted. There is far too much data to manually copy out, so I am trying to use a Macro. I am not very skilled with VBA, but I know a little (probably just enough to break something :) ).
I am just working on 1 sheet right now, but there are several sheets, all formatted in the same way. Here is a snippet of what the source data looks like:
I highlighted the cells that I am needing to copy. The rest of the data is not important and won't need to be extracted.
As you can see, the source data is not formatted as traditional rows and columns, to say the least.
I am copying this data into a table that I have set up in a new sheet.
****Edit:**** I updated my code. I realized that the data was formatted to where there are the same amount of spaces between the rows in the data that I need, 14 to be exact. I now have a Do While Loop that increments the Row Index by 14 each time to move to the next record.
This code works, but am I going about this the correct way??? I will need to repeat this process for about 50 sheets, some of which have 1000 or more records.
Sub CopyData()
Dim SourceSheet As Worksheet
Dim DestSheet As Worksheet
Dim DestRow As Long
Dim i As Integer
i = 0
Set SourceSheet = Sheets("Sheet1")
Set DestSheet = Sheets("Data")
Do While i < 100
DestRow = DestSheet.Cells(Rows.Count, "A").End(xlUp).Row + 1
SourceSheet.Cells(2 + i, 1).Copy
DestSheet.Range("A" & DestRow).PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
SourceSheet.Cells(2 + i, 2).Copy
DestSheet.Range("D" & DestRow).PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
SourceSheet.Cells(3 + i, 2).Copy
DestSheet.Range("E" & DestRow).PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
SourceSheet.Cells(4 + i, 2).Copy
DestSheet.Range("F" & DestRow).PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
SourceSheet.Cells(2 + i, 7).Copy
DestSheet.Range("C" & DestRow).PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
SourceSheet.Cells(5 + i, 7).Copy
DestSheet.Range("G" & DestRow).PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
SourceSheet.Cells(14 + i, 2).Copy
DestSheet.Range("B" & DestRow).PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
i = i + 14
Loop
End Sub
Yes, I think what you are doing is good. You've figured out the pattern and how to increment through it. You probably want to add some kind of check for when you've reached the end of a sheet - the simplest would be to test for a blank in the first line after the Do and exit that loop with an Exit Do which will kick you into an outer loop like For each ws in wb.Worksheets.
This isn't a very technical answer I know, but it seems like you're very close and I didn't want to type all this in a comment.
I am posting the almost final code I came up with here in case it can help any one in the future. It turned out to not be quite as hard as I thought, once I discovered there was equal spacing in the data. Thanks #Doug Glancy for your advice on using Exit Do.
I am sure this is far from a perfect solution. Need to add some error handling/checking. I would appreciate any advice on ways that the code could be improved, or different ways to accomplish this.
Sub CopyData()
Dim DestSheet As Worksheet
Dim DestRow As Long
Dim i As Integer
Set DestSheet = Sheets("Data")
'Loop through all worksheets in the workbook
For Each Worksheet In ActiveWorkbook.Worksheets
'Reset counter variable for each worksheet
i = 0
'Check to make sure we are not on the destination sheet
If Worksheet.Name <> DestSheet.Name Then
'Loop through all rows in the sheet
Do While i < Worksheet.Rows.Count
'Check the contents of the first row in the record to ensure that it contains data
If Worksheet.Cells(2 + i, 1) <> "" Then
'Find the next empty row in the destination sheet to copy to
DestRow = DestSheet.Cells(Rows.Count, "A").End(xlUp).Row + 1
'Copy and paste data, using paste special because of the formatting and formulas in the source
Worksheet.Cells(2 + i, 1).Copy
DestSheet.Range("A" & DestRow).PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
Worksheet.Cells(2 + i, 2).Copy
DestSheet.Range("D" & DestRow).PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
Worksheet.Cells(3 + i, 2).Copy
DestSheet.Range("E" & DestRow).PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
Worksheet.Cells(4 + i, 2).Copy
DestSheet.Range("F" & DestRow).PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
Worksheet.Cells(2 + i, 7).Copy
DestSheet.Range("C" & DestRow).PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
Worksheet.Cells(5 + i, 7).Copy
DestSheet.Range("G" & DestRow).PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
Worksheet.Cells(14 + i, 2).Copy
DestSheet.Range("B" & DestRow).PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
'Add 14 to counter, since the rows are equally spaced by 14
i = i + 14
Else
'If the first row contains no data, then exit the loop
Exit Do
End If
Loop
End If
Next
End Sub

Resources