I am trying to copy only the values from a table to a different sheet, however the below code is only copying the formulas thus losing references. I have tried different solutions such as adding .Value to .DataBodyRange.Copy Cells(i,1) however didn't work.
Thanks for your help
Sub loadData()
Application.AutoCorrect.AutoFillFormulasInLists = False
Dim wsh As Worksheet, i&
Application.ScreenUpdating = 0
With ActiveSheet.ListObjects(1)
If ActiveSheet.FilterMode Then .Range.AutoFilter
.DataBodyRange.Delete
i = 4
For Each wsh In ThisWorkbook.Worksheets
If wsh.Name <> "Template" Then
With wsh.ListObjects(4)
.DataBodyRange.Copy Cells(i, 1)
i = i + .ListRows.Count
End With
End If
Next wsh
.Range.AutoFilter Field:=5
End With
Application.ScreenUpdating = 1
End Sub `
This question might help you. Try changing the format (values or formulas) when pasting the values using pastespecial.
You are already using loops to accomplish your checks. You should use loops to finish the job and don't worry about using the clipboard to copy and paste. I can understand using copy and paste especially if you don't understand loops, but you clearly do.
You can do another loop where you set the values for the cells one at a time.
LastCol = Sheets("Sheet1").Cells(1, Columns.count).End(xlToLeft).Column 'Get last column of row with data
For col = 1 To LastCol
Sheets("Sheet2").Cells(i, col).Value = Sheets("Sheet1").Cells(i, col).Value
Next col
This isn't a complete solution, but if you insert this into your code where you are trying to copy and paste, you should get a good idea of how to complete this. Again, I'd avoid using copy and paste macros, simply because it's quicker to just write a three or four line loop in VBA than to record a macro, then edit it, clean it up, modify it, and debug it. It sure seems like less work to "record a macro" but in my experience, the code is quicker and more accurate. You know exactly what is happening instead of some parameters you might not want to question and don't know what they do.
Related
I added a macro to copy a worksheet to another worksheet, so that any changes made after that point can be compared to the original. However, my macro copies over formulas instead of just the values, so when something changes, both sheets change, and the copy serves no purpose. What I have is:
Worksheets("First Sheet").Cells.Copy _
Destination:=Worksheets("Second Sheet").Cells
Is there an easy way to fix this? Thanks!
You need to use Copy >> PasteSpecial and paste only values, this is a 2-line syntax:
Worksheets("First Sheet").Cells.Copy
Worksheets("Second Sheet").Cells.PasteSpecial xlPasteValues
After your macro, you can write this one:
With Worksheets("First Sheet")
Worksheets("Second Sheet").Range(.UsedRange.Address).Cells.Value2 = .UsedRange.Value2
End With
It takes the values of the first sheet and it puts them to the second sheet. The trick with UsedRange is needed, because Worksheets(2).Cells.Value2 = Worksheets(1).Cells.Value2 goes above the usual resources of a normal PC.
This will skip all formula cells in the first sheet:
Sub KopyKat()
Dim r As Range, addy As String
For Each r In Worksheets("First Sheet").Cells.SpecialCells(2)
addy = r.Address
r.Copy Destination:=Worksheets("Second Sheet").Range(addy)
Next r
End Sub
I have a xlsx spreadsheet with a bunch of sheets that either contain data or formulas. Lets say sheet1 has the data and sheet2 has formulas referring to the data in sheet1. I'm trying to do the following when sheet1 is updated with new data (coming from a SAS program):
convert sheet2 to only values (i.e. remove the formulas behind)
delete sheet1
save file
I would need to automate this througout the spreadsheet and have the macro/program run automaticcaly when there's an update.
So far, here's what I got (pasting values instead of formulas):
Sub Sample()
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("tab2")
ws.UsedRange.Value = ws.UsedRange.Value
End Sub
I am really not familiar with VBA.
You've got the values only in Sheet2.
You want to delete Sheet1 (there should be a pop-up to check if you really want to delete the sheet... we're going to turn that off before you do, then back on after):
Application.DisplayAlerts = False
Sheets("Sheet1").Delete
Application.DisplayAlerts = True
Then to .SaveAs (prompts for file name to save as)
ThisWorkbook.SaveAs Filename:=fName
Try this:
Sub Sample()
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("tab2")
ws.UsedRange.Value = ws.UsedRange.Value
Application.DisplayAlerts = False
Sheets("sheet1").Delete
Application.DisplayAlerts = True
ActiveWorkbook.Save
End Sub
Why not just scratch the idea of two sheets and extrapolate on the answer I got in my question.
Use formula to update cells, but as values
Try a macro with
Range("A1:P10").Select
With Selection
.Value = .Value
End With
This will turn every formula in the range you've selected into it's value. Just don't try using Cells.Select. When I tried it, I got a memory related error. If your spreadsheets are various sizes, then calculate the bottom cell first.
Sub Convert()
' Table Bottom
Dim TB As Long
' Set Table Bottom Variable
TB = Range("A65000").End(xlUp).Row 'finds bottom row
' Change Formulas in Range to Values
Range("A1:P" & TB).Select
With Selection
.Value = .Value
End With
End Sub
Sometimes I have to change the column for finding the bottom row depending on the spreadsheet, but this is the general idea.
I think this will accomplish what you're ultimately trying to do if you put this at the end of the code that is pulling the updates, or if you just run it separately after the updates have been completed. It doesn't seem like your goal is to have two different spreadsheets. Just one spreadsheet that is only values.
I'm writing a function to change an entire column to new values using a formula, here's the code I'll elaborate more on the idea down there.
The problem is that it hangs and I have to rerun Excel and I'm not sure why.
Sub Button2_Click()
Dim i As Long
For i = 2 To Rows.Count
Cells(i, 4).Formula = "=B" & i & "+6*3600000/86400000+25569"
Next i
End Sub
So what's this about? I'm changing the fourth column to excel time because what I have in column B is epoch time, and this is the formula I'm using, it works with my case if I tried one by one, but for some reason it won't work as a whole. I'm not sure what's done wrong? But I'd appreciate your help.
Writing to cells one-by-one is very slow.
Writing formulas one-by-one is slower still, because each must be evaluated before Excel accepts them as formulas.
Doing this a million times can literally freeze Excel.
The solution is to write them all in one shot (no loops):
Sub Button2_Click()
[d2:d1048576] = "=B2+6*3600000/86400000+25569"
End Sub
' Another way of doing mass calculation is by using copy and paste method.
It will be better to convert the columns into values so that the sheet won't calculate again and again. It helps to prevent the sheet from hanging issues
Sub Button2_Click()
Range("D2").Formula = "=b1" & "+6*3600000/86400000+25569"
Range("D2").Copy
Range("D2:d1048576").PasteSpecial xlValues
Application.CutCopyMode = False
Range("D:D").Value = Range("D:D").Value
End Sub
I have data on multiple sheets in a workbook that I want copied all to one sheet in that same workbook. When I run the macro, I would like it to start by deleting the current data in the "iPage Data Export" sheet and then replacing it with data from the other sheets.
I want the process to occur one column at a time since I may not bring over everything. Right now I am trying to learn how to do just one column.
I was able to get it to copy all of the contents of a column from one sheet, but when it moves to the next sheet, it overwrites the existing data. In the end, I only get one sheets worth of data copied.
Here are my 4 problems:
How do I make it clear the data on this sheet before running the routine?
How can I make it start each copy function at the bottom of that row (i.e. after the last cell with a value)? I have tried many of the suggestions on this and other boards without success. I will admit I am not very experienced in this.
How can I make it copy to a particular column (currently it just seems to default to A.
How can I concatenate multiple columns during the paste function? I.e. what if I want it to insert: A2&", "B2 instead of just A2
Sub CombineData()
Dim Sht As Worksheet
For Each Sht In ActiveWorkbook.Worksheets
If Sht.Name <> "iPage Data Export" Then
Sht.Select
Range("C:C").Copy
Sheets("iPage Data Export").Select
ActiveSheet.Paste
Else
End If
Next Sht
End Sub
How do I make it clear the data on this sheet before running the routine?
Sht.Cells.ClearContents
How can I make it start each copy function at the bottom of that row (i.e. after the last cell with a value)? I have tried many of the suggestions on this and other boards without success. I will admit I am not very experienced in this.
Range("C" & Rows.Count).End(xlUp).Offset(1, 0)
In detail:
Rows.Count will return the number of rows in the sheet, so in the legacy style *.xls workbooks this would return the number 65,536. Therefore "C" & Rows.Count is the same as C65536
Range("C" & Rows.Count).End(xlUp) is the same as going to C65536 and pressing Ctrl + ↑ - The command End(xlDirection) tells the program to go the last cell in that range. In this case, we would end up at the last cell containing data in column C.
.Offset(1, 0) means that we want to return the range offset by an amount of rows and/or columns. VBA uses RC (Rows Columns) references, so whenever you see something like the Offset() function with two numbers being passed as the arguments, it usually relates to the row, and the column, in that order. In this case, we want the cell that is one row below the last cell we referenced.
All-in-all the phrase Range("C" & Rows.Count).End(xlUp).Offset(1, 0) means go to the last cell in column C, go up until we hit the last cell with data, and then return the cell below that - which will be the next empty cell.
How can I make it copy to a particular column (currently it just seems to default to A.
Range("C:C").Copy Destination:=Sheets("iPage Data Export").Range("A:A")
You can pass the Destination argument in the same line and actually bypass the clipboard (faster and cleaner)
How can I concatenate multiple columns during the paste function? I.e. what if I want it to insert: A2&", "B2 instead of just A2
Lets say you wanted to reference column A, B, and F - just use:
Range("A1, B1, F1").EntireColumn
To summarise, you could streamline your existing code to something like (untested):
Sub CombineData()
Dim Sht As Worksheet
For Each Sht In ActiveWorkbook.Worksheets
If Sht.Name <> "iPage Data Export" Then
Sht.Range("C1:C" & Cells(Sht.Rows.Count, 3).End(xlUp).Row).Copy Destination:=Sheets("iPage Data Export").Range("A:A")
End If
Next
End Sub
This should do for the copying:
Sub CombineData()
Dim sheet As Worksheet
For Each sheet In Worksheets
If (sheet.Name <> "iPage Data Export") Then
sheet.Select
Range("A1", ActiveCell.SpecialCells(xlLastCell)).Select
Selection.Copy
Worksheets("iPage Data Export").Activate
Cells(1, ActiveCell.SpecialCells(xlCellTypeLastCell).Column + 1).Select
ActiveSheet.Paste
End If
Next
End Sub
For the concatenation you need to be more specific - but I guess you should open a new question with a clearer focus if you need specific help on that.
So far I have this code below; counting last cell is working fine but is copy/pasting the wrong data to wrong sheet. Should copy data and use the formula from Sheet "Parsing" cell B2, and its using the main sheet where is the VBA. Looks lile what is missing is to execute the copy/select to "parsing" sheet, but didnt manage to do it.
Sub drag_formula_original()
Dim myLastRow As Long
With Worksheets("Parsing")
myLastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
.Range("B2").Copy Destination:=.Range("B2:B" & myLastRow)
Application.CutCopyMode = False
End With
End Sub
Its solved. Thanks a lot.
Range("B2").Copy
The above will grab by default from the Activesheet
you have to tell it what sheet you would like it to pick that range/value from.
sheets("Parsing").Range("B2").Copy
Edit: Just noticed your With
To actually use a with you need to use a "." e.g. your copy line would look like below
.Range("B2").Copy
One other thing to note this:
Range("B2:B" & myLastRow).Select
ActiveSheet.Paste
Is rather inefficient, below would be better. Selecting in general is best to keep away from it is rather slow
Range("B2:B" & myLastRow).Paste
Or with your with
.Range("B2:B" & myLastRow).Paste
I just copied and pasted your code and ran it. I changed nothing in your code except for adding "Option Explicit" before your sub. (Just a personal habit)
Option Explicit
Sub drag_formula_original()
Dim myLastRow As Long
With Worksheets("Parsing")
myLastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
Range("B2").Copy
Range("B2:B" & myLastRow).Select
ActiveSheet.Paste
Application.CutCopyMode = False
End With
End Sub
I did, however, use a very simple formula in cell B2. What I did was have column A go from 1 to 10 and column C go from 11 to 20. Cell B2 was =A2+C2.
After running the code I checked each cell in column B and they each had the correct formula in them, and not a hard-coded value.
A trick I do when I want to do something like this but can't figure out how is I record a macro of me dragging the cell formula down a little ways and then stop the recording and look at the code it made. From that you should be able to adjust it to do what you want.
When I did that I got this code:
Sub Macro1()
'
' Macro1 Macro
'
'
Range("B2").Select
Selection.AutoFill Destination:=Range("B2:B15"), Type:=xlFillDefault
Range("B2:B15").Select
End Sub