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

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

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

Copying columns from multiple sheets into one sheet in the same workbook using VBA

My goal is to automatically copy a range of columns (A:C) from 40+ Excel Sheet into one Sheet located in the same workbook.
The structure of all sheets is identical. Columns consist of numeric values. I want the columns to be added to the right at each iteration (so the target sheet will be enriched horizontally with the data)
My attempt (see the code below) is not automated as if I have to specify Sheet Names and Target Cell where it is possible to copy the columns
Sub macro()
Sheets("Top").Select
Columns("A:C").Select
Selection.Copy
Sheets("Low").Select
Range("D1").Select
ActiveSheet.Paste
End Sub
Any help is appreciated! Thank you
Please, try the next code. It will iterate between all existing sheets and copy all rows of columns "D:K" from all sheets in one named "Destination" (starting from "A1"). If you need it to start from "D1" it would be easy to adapt the code:
Sub copyAllSheetsInOne()
Dim ws As Worksheet, sh As Worksheet, lastRow As Long, lastEmptyCol As Long, i As Long
Set sh = Worksheets("Destination") 'a sheet named "Destination" must exist in the workbook to be processed
sh.cells.ClearContents 'clear its content (for cases when code run before)
'some optimization to make the code faster:
Application.DisplayAlerts = False: Application.EnableEvents = False
Application.Calculation = xlCalculationManual
'iterate between all existing sheets:
For Each ws In ActiveWorkbook.Worksheets
If ws.name <> "Destination" Then
lastEmptyCol = sh.cells(1, sh.Columns.count).End(xlToLeft).Column + 1
lastRow = ws.Range("D" & ws.rows.count).End(xlUp).row
If lastEmptyCol = 2 Then lastEmptyCol = 1 'for the first sheet
ws.Range("D1", ws.Range("K" & lastRow)).Copy sh.cells(1, lastEmptyCol)
End If
Next ws
Application.DisplayAlerts = True: Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
End Sub

Splitting data blocks based on title and copying into sheets named after them

I have a report I receive once a week with multiple data blocks that have dynamic rows and columns and each data block has a static title that will never change that are separated by a blank row. I am trying to copy these blocks into sheets based off of these titles.
I have a script that is creating the sheets and blank rows between data blocks with Python. But I am hoping to do the rest with VBA. Here is the end result Example.
Currently each of those sheets are blank, and I want to either copy paste or cut and paste the blocks into those sheets without their titles. i.e. A41:C46 into the Unanswered Service Level sheet.
Sub FormatExcel()
Dim LR As Long, i As Long
With Sheets("Master")
LR = .Range("A" & Rows.Count).End(xlUp).Row
For i = 1 To LR
With .Range("A" & i)
If .Value = "All Call Distribution by Queue" Then
ActiveCell.CurrentRegion.Select
Selection.Copy
Sheets("All Calls by Queue").Select
ActiveSheet.Paste
End If
End With
Next
End With
End Sub
This is what I have so far.
It will copy/paste into the designated sheet. But I'm stuck on why it's adding a second blank row at the top and how to code it so that if the sheet doesn't exist then nothing will happen. I am very new to VBA but I pieced this together from other code and just recording macros. Otherwise I was just going to copy and paste this code 15 times just with different sheet titles and .Values
You can use an approach like this:
Sub FormatExcel()
Dim ws As Worksheet, wb As Workbook
Set wb = ThisWorkbook 'ActiveWorkbook?
Set ws = wb.Worksheets("Master")
CopyBlock ws, "All Call Distribution by Queue", "All Calls by Queue"
CopyBlock ws, "Title2", "Title2 sheet"
'etc etc
End Sub
Sub CopyBlock(ws As Worksheet, title As String, destWS As String)
Dim f As Range, rng As Range, wsDest As Worksheet
'check if destination worksheet is present
On Error Resume Next 'ignore any error
Set wsDest = ws.Parent.Worksheets(destWS) 'check in same workbook as `ws`
On Error GoTo 0 'stop ignoring errors
If wsDest Is Nothing Then
Debug.Print "Missing sheet '" & destWS; "' in workbook '" & ws.Parent.Name & "'"
Exit Sub
End If
Set f = ws.Columns("A").Find(what:=title, lookat:=xlWhole) 'search header
If Not f Is Nothing Then 'got a match?
Set rng = f.CurrentRegion
Set rng = rng.Offset(1, 0).Resize(rng.Rows.Count - 1) 'exclude header row
rng.Copy wsDest.Range("A1") 'copy to specific location
End If
End Sub

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

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.

VBA Copy specific rows from multiple sheets with their names containing "Hawk" and paste into new sheet

I have a workbook containing multiple spreadsheets. Some of these spreadsheets contain the word "Hawk" in their name. For instance, "12345 - HAWK" and "ABCDE - Hawk". I need to copy data from these sheets starting from row 38 down to however many rows that Hawk sheet contains and paste this into a new spreadsheet.
I have this code that I got from another thread, but it is only pasting the rows from the last sheet that contains the word "Hawk". I need it to paste from EVERY sheet that contains "Hawk" in the name, not just the last one.
I don't have any experience in VBA, so I'm not sure what is going wrong. Any advice would be greatly appreciated.
Option Explicit
Sub compile()
SelectSheets "Hawk", ThisWorkbook
'Some other bits and pieces here
End Sub
Sub SelectSheets(sht As String, Optional wbk As Workbook)
Dim wks As Worksheet
Dim ArrWks() As String
Dim i As Long
If wbk Is Nothing Then Set wbk = ActiveWorkbook
ReDim ArrWks(0 To Worksheets.Count - 1)
For Each wks In Worksheets
If InStr(1, wks.Name, sht) > 0 Then
ArrWks(i) = wks.Name
i = i + 1
End If
Next wks
ReDim Preserve ArrWks(i - 1)
Dim ws As Long
For ws = LBound(ArrWks) To UBound(ArrWks)
Worksheets(ArrWks(ws)).Range("A37:AC100").Copy
Worksheets("VBA").Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).PasteSpecial (xlPasteValues)
Next ws
Application.CutCopyMode = False
Application.ScreenUpdating = True
End Sub
Public Sub compile()
Dim sh As Worksheet, lastrow As Long, lastcol As Long, i As Long
i = 1 'For paste data in first row in MasterSheet.
Sheets("MasterSheet").Cells.ClearContents 'Clear previous data.
For Each sh In ThisWorkbook.Worksheets
If InStr(1, UCase(sh.Name), UCase("HAWK")) > 0 Then
'IF your data is inconsistent then use find function to find lastrow an lastcol.
lastrow = sh.Cells(Rows.Count, 1).End(xlUp).Row
lastcol = sh.Cells(38, Columns.Count).End(xlToLeft).Column
'Here we collect data in master sheet.
Sheets("MasterSheet").Range("A" & i).Resize(lastrow - 38 + 1, lastcol).Value = sh.Range("A38", sh.Cells(lastrow, lastcol)).Value
i = i + lastrow - 38 + 1
End If
Next sh
End Sub
Use this one instead of your code..It will collect all the data from range "A38" to last row and column and paste in mastersheet..Check this and let me know if it works.

Resources