Macro to copies value of a cell to another sheet but retain destination Format - excel

I have a Sheet named "Daily Data" and One Sheet named "JPY Dly". I created a button and wrote a Macro to import data from another file and place into cells A1:D1 in "Daily Data".
I then need to Copy and Paste those VALUES into the next available cells in specific columns of Sheet "JPY Dly".
I used Offset in the Paste portion of the code but when the Paste occurs, the data does not keep the destination cells formatting. All I want is the VALUES of the cells in "Daily Data" to be copied over and for them to assume the pre-determined formatting of cells in "JPY Dly".
Here is the code that I am using.
Sub Import_DailyData()
Workbooks.Open "C:\Users\dbrown1\Downloads\exchange.csv"
'Opens the dowloaded file from the web
Workbooks("exchange.csv").Worksheets("exchange").Range("A8:AN9").Copy _
Workbooks("FOREX TEST.xlsm").Worksheets("Daily Data").Range("A1")
'Copies the daily data into FOREX Workbook
Workbooks("exchange.csv").Close SaveChanges:=False
'Closes the downloaded sheet without saving
Kill ("C:\Users\dbrown1\Downloads\exchange.csv")
'Insert the "Write to sheets" portion of the Sub in here
Worksheets("Daily Data").Range("A2").Copy Sheets("JPY Dly").Range("C2000").End(xlUp).Offset(1, 0)
Worksheets("Daily Data").Range("F2").Copy Sheets("JPY Dly").Range("E2000").End(xlUp).Offset(1, 0)
Worksheets("Daily Data").Range("G2").Copy Sheets("JPY Dly").Range("F2000").End(xlUp).Offset(1, 0)
Worksheets("Daily Data").Range("E2").Copy Sheets("JPY Dly").Range("G2000").End(xlUp).Offset(1, 0)
'Below this you will see the ClearContents portion of the code
Worksheets("Daily Data").Range("A1:AN2").ClearContents
End Sub
Can you please tell me how to paste the Values only from "Daily Data" and them assume the formatting of the cells in "JPY Dly"?
UPDATE
Here is updated code recommended by chrisnielsen and the screenshot from the downloaded "exchange"file.
Sub Import_DailyData()
Dim wbCSV As Workbook
Dim wsCSV As Worksheet
Dim wsDestination As Worksheet
Dim DestRow As Long
Set wbCSV = Workbooks.Open("C:\Users\dbrown1\Downloads\exchange.csv")
Set wsCSV = wbCSV.Worksheets("exchange")
'Opens the dowloaded file from the web
Set wsDestination = ThisWorkbook.Worksheets("JPY Dly")
'Copies the daily data into FOREX Workbook
'Closes the downloaded sheet without saving
'Insert the "Write to sheets" portion of the Sub in here
With wsDestination
DestRow = .Cells(.Rows.Count, 3).End(xlUp) + 1
' Copy data
.Cells(DestRow, 3).Value = wsCSV.Cells(2, 1).Value
.Cells(DestRow, 5).Value = wsCSV.Cells(2, 3).Value
.Cells(DestRow, 6).Value = wsCSV.Cells(2, 4).Value
.Cells(DestRow, 7).Value = wsCSV.Cells(2, 2).Value
End With
'Below this you will see the ClearContents portion of the code
'Worksheets("Daily Data").Range("A1:AN2").ClearContents
Workbooks("exchange.csv").Close SaveChanges:=False
'Kill ("C:\Users\dbrown1\Downloads\exchange.csv")
End Sub

While Copy/Paste Values will work, it's cleaner to use the values properties of the source and destination cells. This will retain destination cell formats.
Also, there are a number of other opertunities for improvement
Use Workbook and Workssheet references
No need for the intermediate Daily Data Sheet.
No need to repeat the .End(xlUp) bits
No need for the ( ) on the Kill line (in fact this has side effects that, while not a problem here, will eventually bite you)
Sub Import_DailyData()
Dim wbCSV As Workbook
Dim wsCSV As Worksheet
Dim wsDestination As Worksheet
Dim DestRow As Long
'Open the dowloaded file from the web, and get references
Set wbCSV = Workbooks.Open("C:\Users\dbrown1\Downloads\exchange.csv")
Set wsCSV = wbCSV.Worksheets("exchange")
' Reference the destination
Set wsDestination = ThisWorkbook.Worksheets("JPY Dly") ' Assuming FOREX TEST.xlsm contains this code
' If FOREX TEST.xlsm does not contains this code, use this instead of the previous line
'Set wsDestination = Application.Workbooks("FOREX TEST.xlsm").Worksheets("JPY Dly")
' get destination row
With wsDestination
DestRow = .Cells(.Rows.Count, 3).End(xlUp).Row + 1
' Copy data
.Cells(DestRow, 3).Value = wsCSV.Cells(2, 1).Value
.Cells(DestRow, 5).Value = wsCSV.Cells(2, 6).Value
.Cells(DestRow, 6).Value = wsCSV.Cells(2, 7).Value
.Cells(DestRow, 7).Value = wsCSV.Cells(2, 5).Value
End With
'Close and delete the downloaded workbook without saving
wbCSV.Close SaveChanges:=False
Kill "C:\Users\dbrown1\Downloads\exchange.csv"
End Sub

Building on ACCitonMan's comment to use paste special. The following code takes the text from cell A1 and pastes it into cell A2 while keeping whatever formatting is in cell A2.
Sub pasteSpec()
Dim ws As Excel.Worksheet
Dim cRng As Excel.Range
Dim pRng As Excel.Range
Set ws = ThisWorkbook.Worksheets(1)
Set cRng = ws.Range("A1")
Set pRng = ws.Range("A2")
cRng.Copy
pRng.PasteSpecial Paste:=xlPasteValuesAndNumberFormats
Application.CutCopyMode = False 'stops marching ants when using .copy
End Sub
Additional paste types can be found in the documentation here.

Related

Looking to find the last row on my sheet where there is another record of it, then copy and paste data below

I am in the process of trying to create a Macro so that we can press a button and it updates the whole sheet.
Essentially all my data is being collected from another workbook, but it has to be non macro hence all my data is pulling through to my sheet Do Not Delete.
I have got my Macro to cycle through and copy/paste as values onto another sheet and remove all the rows that contain the text '#VALUE!'.
I have tried searching around on how to do this, but to no avail. I am trying to find out how to search each row on the 'Do Not Delete' sheet for the value that is in Column G on each row for anywhere that this exists elsewhere in the workbook, but I am unable to do this. From the point that I find the last record where it exists, I want to then copy down from there onwards.
Sub CopyToSheet()
'
' CopyToSheet Macro
Dim wb As Workbook
Dim ws, wscopy, wsdnd As Worksheet
Dim i, LastRowa, LastRowd As Long
Dim WSheet As String
Dim SheetName As String
Set wsdnd = Sheets("Do Not Delete")
Set wscopy = Sheets("CopyAndClear")
Set wb = ActiveWorkbook
Set ws = ActiveWorkbook.Sheets("Macro - Do not delete")
'Finding Sheet to use
SheetName = Range("L2")
Debug.Print Range("L2")
'Clear Contents
wscopy.Activate
wscopy.Cells.Clear
'Activating Do Not Delete Sheet to copy the data
wsdnd.Activate
LastRowa = wsdnd.Cells(Rows.Count, "A").End(xlUp).Row
wsdnd.Range("A1:IP" & LastRowa).Select
wsdnd.Range("A1:IP" & LastRowa).Copy
'Copy and paste cells onto new sheet
wscopy.Activate
wscopy.Range("A1").PasteSpecial xlPasteValues
Application.CutCopyMode = False
'Apply Filter
Application.DisplayAlerts = False
LastRowc = wscopy.Cells(Rows.Count, "A").End(xlUp).Row
wscopy.Range("A1:IP" & LastRowc).AutoFilter Field:=1, Criteria1:="#VALUE!"
'Delete Rows
wscopy.Range("A1:IP" & LastRowc).SpecialCells(xlCellTypeVisible).Delete
'Clear Filter
On Error Resume Next
wscopy.ShowAllData
On Error GoTo 0
End Sub

How to copy the data from one Workbook and paste the value only in another Workbook and allow macro to run only one time?

When I accidentally run VBA code to copy/paste data from one Workbook to the target Workbook multiple times, it will create multiple rows with same data in the target Worksheet.
I want the VBA code to recognize the previous line is the same, to prevent data duplication.
Further, my VBA code will copy the formulas to my destination Excel file.
I want to copy the value only instead of the formula. I'm not sure how to use PasteSpecial in my VBA code.
Sub Copy_Paste_Below_Last_Cell()
Dim wsDest As Worksheet
Dim lDestLastRow As Long
Set wsDest = Workbooks("Destination.xlsx").Worksheets("DataBase")
lDestLastRow = wsDest.Cells(wsDest.Rows.Count, "C").End(xlUp).Offset(1).Row
' How to use PasteSpecial Paste:=xlPasteValues here?
Sheet4.Range("B6:F6").Copy wsDest.Range("C" & lDestLastRow)
End Sub
Edit:
Sub Copy_Paste_Below_Last_Cell1()
Dim wsDest As Worksheet
Dim lDestLastRow As Long
Set wsDest = Workbooks("Destination.xlsx").Worksheets("DataBase")
lDestLastRow = wsDest.Cells(wsDest.Rows.Count, "C").End(xlUp).Offset(1).Row
If sheetWithVariable.CellWithVariable.Value = False Then
Sheet4.Range("B6:F6").Copy
wsDest.Range("C" & lDestLastRow).PasteSpecial Paste:=xlPasteValues
sheetWithVariable.CellWithVariable.Value = True
End If
End Sub
Task: copy from main workbook and paste in target workbook
without duplicating data.
This should do it. Adjust the config section of the code before trying it.
Sub TransferData()
Dim main_wb As Workbook, target_wb As Workbook, main_sheet As String
Dim r As String, target_sheet As String, first_col As Byte, col_n As Byte
Dim next_row As Long, duplicates As Byte, pasted As Byte, last_col As Long
'CONFIG HERE
'------------------------
Set main_wb = ThisWorkbook
main_sheet = "Sheet1"
r = "B6:F6" 'range to copy in the main Workbook
'target workbook path
Set target_wb = _
Workbooks.Open("/Users/user/Desktop/target workbook.xlsm")
target_sheet = "Sheet1"
first_col = 3 'in what column does the data starts in target sheet?
'-------------------------
'turn screen updating off
Application.ScreenUpdating = False
'copy from main
main_wb.Sheets(main_sheet).Range(r).Copy
With target_wb.Sheets(target_sheet)
'target info
next_row = _
.Cells(Rows.Count, first_col).End(xlUp).Row + 1
'paste in target
.Cells(next_row, first_col).PasteSpecial xlPasteValues
last_col = _
.Cells(next_row, Columns.Count).End(xlToLeft).Column
End With
pasted = last_col - (first_col - 1)
For col_n = first_col To last_col
With target_wb.Sheets(target_sheet)
If .Cells(next_row, col_n) = .Cells(next_row - 1, col_n) Then
duplicates = duplicates + 1
End If
End With
Next col_n
If duplicates = pasted Then 'if the nº of cells pasted equals duplicates
For col_n = first_col To last_col 'erase pasted range
target_wb.Sheets(target_sheet).Cells(next_row, col_n).Clear
Next col_n
End If
'turn screen updating back on
Application.ScreenUpdating = True
End Sub
Go "Developer Tab" then press "Record macro" or at Excel bottom left side there is small button "Record macro". Then you press it it will create automatically code for every your click, press and etc., so go copy and paste only values, stop recording macro. And you will have Module1 with code how to "paste values".
For PasteSpecial function, copying and pasting are defined as different operations (so as to say, no Destination option should be used for Copy):
Sheet4.Range("B6:F6").Copy
wsDest.Range("C" & lDestLastRow).PasteSpecial _
Paste:=xlPasteValues
If you want your to code to run once, add a variable somewhere in your workbook that will specify that the code already run. Something like that:
Sub Copy_Paste_Below_Last_Cell()
If sheetWithVariable.CellWithVariable.Value = False Then
' Put your code here
sheetWithVariable.CellWithVariable.Value = True
End If
End Sub

paste special by value with destination vba

I need to paste special by values the data to my destination. I am not able to work it out. Please can someone help. thank you
Sub ExtractData()
Dim lastrow As Long
Dim erow As Long
Dim i As Long
'Dim mydate As Date
Dim myVIN As String
lastrow = Worksheets("Page1_1").Cells(Rows.Count, 1).End(xlUp).Row
Worksheets("Page1_1").Select
Worksheets("Page1_1").Range("L1").Select
For i = 2 To lastrow
myVIN = Cells(i, 1)
If myVIN <> "#N/A" Then
erow = Worksheets("OASIS Lookup").Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
Cells(i, 12).copy Destination:=Sheets("OASIS Lookup").Cells(erow, 1)
End If
Next i
End Sub
'Assign' Instead of PasteSpecial xlPasteValues
Avoid Select and any flavor of Active.
Use variables.
So what if the code is longer, but you will still be able to understand it in a week, a month or even a year. The code will not run faster if it has fewer lines.
Use comments to describe what the code is doing. Not so many as I did but more moderately.
The Code
Option Explicit
Sub ExtractData()
' Define workbook and worksheets.
' Define workbook.
Dim wb As Workbook
Set wb = ThisWorkbook ' The workbook containing this code.
' Define Source Worksheet.
Dim src As Worksheet
Set src = wb.Worksheets("Page1_1")
' Define Source Last Row.
Dim srcRow As Long
srcRow = src.Cells(src.Rows.Count, 1).End(xlUp).Row
' Define Target Worksheet.
Dim tgt As Worksheet
Set tgt = wb.Worksheets("OASIS Lookup")
' Define Target Current Row.
Dim tgtRow As Long
tgtRow = tgt.Cells(tgt.Rows.Count, 1).End(xlUp).Row
' Write values from Source Worksheet to Target Worksheet.
' Declare a variable to hold each value in Criteria Column (1).
Dim myVIN As Variant ' Only 'Variant' can accept any value, incl. errors.
' Declare Source Worksheet Rows Counter.
Dim i As Long
' Loop through rows of Source Worksheet.
For i = 2 To srcRow
' Write value in current row of Criteria Column (1) to 'myVIN'.
myVIN = src.Cells(i, 1).Value
' Check if 'myVIN' does not contain an error value.
If Not IsError(myVIN) Then
' Increase Target Current Row.
tgtRow = tgtRow + 1
' Write value in current row of Source Column (12) to current row
' of Target Column (1).
tgt.Cells(tgtRow, 1).Value = src.Cells(i, 12).Value
End If
Next i
' Inform user.
MsgBox "Data copied.", vbInformation, "Success"
End Sub
A rather simple solution could be to replace this line
Cells(i, 12).copy Destination:=Sheets("OASIS Lookup").Cells(erow, 1)
by
Cells(i, 12).copy
Sheets("OASIS Lookup").Cells(erow, 1).PasteSpecial Paste:=xlPasteValues

VBA copy and paste corresponding data onto new sheet

I am trying to use VBA to ask the user to enter a date. For that date, copy all appointments and paste them on sheet “Daily Appts”, one-by-one. My reference sheet that contains all the data corresponding to given dates is named "Appts". I attached a picture for reference. Leading up to this, I created worksheet "Daily Sheet" and copy and pasted the headers from "Appts" onto it. I am trying to get every value for the date entered to copy and paste onto the new sheet but I am stuck. For example, if user enters 10/01/2018, it will have multiple sets of data that needs to be copied over. Here is what I have so far. Step 6 is where I need help to complete the task. 1: https://i.stack.imgur.com/vEtUd.png
'Step 1:
Sub Part2()
Dim sheet As Variant
'Step 2: Add code to delete sheet "Daily Appts", if exist.
For Each sheet In ActiveWorkbook.Worksheets
If sheet.Name = "Daily Appts" Then
Application.DisplayAlerts = False
Worksheets("Daily Appts").Delete
Application.DisplayAlerts = True
End If
Next sheet
'Step 3: Add code to add a new sheet, name it "Daily Appts"
Sheets("Main").Select
Sheets.Add After:=ActiveSheet
ActiveSheet.Select
ActiveSheet.Name = "Daily Appts"
Sheets("main").Select
'Step 4: Add code to select the worksheet "Appts". Name the range that holds
'the title (first row), the range that contains the data, and the range
'contains the schedule.
Sheets("Appts").Select
Dim Title As Range, Data As Range, Schedule As Range
Set Title = Range("A1", Range("A1").End(xlToRight))
Title.Name = "Title"
Set Data = Range("A2", Range("A2").End(xlDown).End(xlToRight))
Data.Name = "Data"
Set Schedule = Range("J2", Range("J2").End(xlDown))
Schedule.Name = "Schedule"
'Step 5: Add code to copy and paste the title into the new sheet, "Daily
'Appts".
Sheets("Appts").Range("Title").Copy 'Copy the data
Sheets("Daily Appts").Activate 'Activate the destination worksheet
Range("A1").Select 'Select the target range
ActiveSheet.Paste 'Paste in the target destination
Application.CutCopyMode = False
'Step 6: Ask the user to enter a date. For that date, copy all appointments
'and paste them on sheet "Daily Appts", one-by-one.
Dim result As String, i As Long, mydate As Date
Sheets("Appts").Select
result = InputBox("Enter a date")
For i = 2 To 360
mydate = Cells(i, 10)
If mydate = result Then
Sheets("Appts").Range("J2").End(xlToLeft).Copy
Sheets("Daily Appts").Activate
Range("A2").End(xlDown).Select
ActiveSheet.Paste
End If
Next
End Sub
There is not reason to loop to test whether a single sheet exists a simple test if a cell reference is valid will do it:
If Not IsError(Application.Evaluate("'Daily Appts'!A1")) Then Worksheets("Daily Appts").Delete
Also by declaring a worksheet variable on the addition it make it easier to work with the sheet later:
Dim ws As Worksheet
Set ws = Worksheets.Add(After:=Worksheets("Main"))
ws.Name = "Daily Appts"
Then there is no need for the range.name as you created the ranges as variables just refer to them.
Then in the loop you need to iterate the copy ranges.
I also cleaned up the .Activate and .Select which should be avoided.
Sub Part2()
'Step 2: Add code to delete sheet "Daily Appts", if exist.
If Not IsError(Application.Evaluate("'Daily Appts'!A1")) Then Worksheets("Daily Appts").Delete
'Step 3: Add code to add a new sheet, name it "Daily Appts"
Dim ws As Worksheet
Set ws = Worksheets.Add(After:=Worksheets("Main"))
ws.Name = "Daily Appts"
'Step 4: Add code to select the worksheet "Appts". Name the range that holds
'the title (first row), the range that contains the data, and the range
'contains the schedule.
With Worksheets("Appt")
Dim lCol As Long
lCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
Dim lRow As Long
lRow = .Cells(.Rows.Count, 1).End(xlUp).Row
Dim Title As Range
Set Title = .Range(.Cells(1, 1), .Cells(1, lCol))
'Step 5: Add code to copy and paste the title into the new sheet, "Daily
'Appts".
Title.Copy ws.Range("A1") 'Paste in the target destination
'Step 6: Ask the user to enter a date. For that date, copy all appointments
'and paste them on sheet "Daily Appts", one-by-one.
Do
Dim result As String
result = InputBox("Enter a date")
If Not IsDate(result) Then MsgBox ("must be date")
Loop Until IsDate(result)
For i = 2 To lRow
If .Cells(i, 10).Value2 = CDate(result) Then
.Range(.Cells(i, 1), .Cells(i, lCol)).Copy ws.Cells(ws.Rows.Count, 1).End(xlUp).Offset(1)
End If
Next
End With
End Sub

deleting excel tabs doesn't reduce file size

In an effort to reduce a 60MB excel file I deleted half the tabs, and many of the formulas on the remaining tabs.
The result didn't budge the overall filesize. Perhaps (as in access) there's a function/addin/? which will compress or recover the space?
I tried to export the tabs to a new file, however, most of the tabs have tables and so is impossible.
btw, the file is already in .XLSB format.
thank you,
-R
Here is my liposuction code I wrote years ago, it will do formulas, text and pics, doesn't do charts currently but you can see how it handles pics and add that in easily enough.
Sub LipoSuction2()
'Written by Daniel Donoghue 18/8/2009
'The purpose of this code is to offer an alternative to the original Liposuction code written by JBeaucaire for the MrExcel forums www.mrexcel.com
Dim ws As Worksheet
Dim CurrentSheet As String
Dim OldSheet As String
Dim Col As Long
Dim r As Long
Dim BottomrRow As Long
Dim EndCol As Long
'Begin addition 6/4/2010 for request: http://www.mrexcel.com/forum/showthread.php?p=2269274#post2269274
Dim Pic As Object
'End Addition 6/4/2010 for request: http://www.mrexcel.com/forum/showthread.php?p=2269274#post2269274
For Each ws In Worksheets
ws.Activate
'Put the sheets in a variable to make it easy to go back and forth
CurrentSheet = ws.Name
'Rename the sheet to its name with TRMFAT at the end
OldSheet = CurrentSheet & "TRMFAT"
ws.Name = OldSheet
'Add a new sheet and call it the original sheets name
Sheets.Add
ActiveSheet.Name = CurrentSheet
Sheets(OldSheet).Activate
'Find the bottom cell of data on each column and find the further row
For Col = 1 To Columns.Count 'Find the REAL bottom row
If Cells(Rows.Count, Col).End(xlUp).Row > BottomRow Then
BottomRow = Cells(Rows.Count, Col).End(xlUp).Row
End If
Next
'Find the end cell of data on each row that has data and find the furthest one
For r = 1 To BottomRow 'Find the REAL most right column
If Cells(r, Columns.Count).End(xlToLeft).Column > EndCol Then
EndCol = Cells(r, Columns.Count).End(xlToLeft).Column
End If
Next
'Copy the REAL set of data
Range(Cells(1, 1), Cells(BottomRow, EndCol)).Copy
Sheets(CurrentSheet).Activate
'Paste everything
Range("A1").PasteSpecial xlPasteAll
'Paste Column Widths
Range("A1").PasteSpecial xlPasteColumnWidths
'Begin addition 6/4/2010 for request: http://www.mrexcel.com/forum/showthread.php?p=2269274#post2269274
Sheets(OldSheet).Activate
For Each Pic In ActiveSheet.Pictures
Pic.Copy
Sheets(CurrentSheet).Paste
Sheets(CurrentSheet).Pictures(Pic.Index).Top = Pic.Top
Sheets(CurrentSheet).Pictures(Pic.Index).Left = Pic.Left
Next
Sheets(CurrentSheet).Activate
'End Addition 6/4/2010 for request: http://www.mrexcel.com/forum/showthread.php?p=2269274#post2269274
'Reset the variable for the next sheet
BottomRow = 0
EndCol = 0
Next
'Excel will automatically replace the sheet references for you on your formulas, the below part puts them back
'This is done with a simple reaplce, replacing TRMFAT with nothing
For Each ws In Worksheets
ws.Activate
Cells.Replace "TRMFAT", ""
Next
'Poll through the sheets and delete the original bloated sheets
For Each ws In Worksheets
If Not Len(Replace(ws.Name, "TRMFAT", "")) = Len(ws.Name) Then
Application.DisplayAlerts = False
ws.Delete
Application.DisplayAlerts = True
End If
Next
End Sub

Resources