excel vba - error 1004 - excel

could you help me out with this problem in my vba code ? (I was trying to go through many topics about 1004 error on forums, yet I am a vba novice and was not able to deal with it..).
there is Table in RaWData sheet with headers - I need to clean the data part, then in next section I am going to copy there some of the data from other sheet where is Pivot table
Error on the line (section 'Sheet RawData cleaning):
RawData.Range(Cells(2, 1), Cells(LastRow, LastCol)).Delete
Not whole code but here is a bit:
'Exporting
Dim FZ As Workbook
Dim Cesta As Variant
Dim i As Long
Dim SubRegion As String
Dim rTable As Range
Dim CurrDate As String
Dim RawData As Worksheet
Dim SFDCReport As Worksheet
Dim MS As Worksheet
Dim DS As Worksheet
Dim DealOffice As Worksheet
Set DS = ThisWorkbook.Sheets("Data")
Set MS = ThisWorkbook.Sheets("Macro")
Cesta = Application.GetOpenFilename
Set FZ = Workbooks.Open(Filename:=Cesta, Local:=True)
Set RawData = FZ.Sheets("RawData")
Set SFDCReport = FZ.Sheets("SFDC Report")
Set DealOffice = FZ.Sheets("Coverage DealOffice")
CurrDate = MS.Range("E1").Value
For i = 1 To PRFilter
'Check if Export column is not empty for each SubRegion, if yes, skip to next Subregion(Iteration)
If IsEmpty(MS.Cells(i + 1, 2).Value) Then
GoTo NextIteration
Else 'Things to do if "Not Empty"
'SubRegion value paste into C10 so Highlights section is updated
SubRegion = MS.Cells(i + 1, 1).Value
SFDCReport.Cells(10, 3).Value = SubRegion
'Sheet SFDC Report Cleaning
With SFDCReport
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
LastCol = .Cells(12, .Columns.Count).End(xlToLeft).Column
.Range(Cells(14, 1), Cells(LastRow, LastCol)).Delete
End With
'Filter, Select & Copy filtered data to SFDCReport table
DS.Range("A1").CurrentRegion.AutoFilter Field:=84, Criteria1:=SubRegion
Set rTable = DS.AutoFilter.Range
Set rTable = rTable.Resize(rTable.Rows.Count - 1)
Set rTable = rTable.Offset(1) 'Move new range down to start at the first data row
rTable.Copy
SFDCReport.Cells(13, 1).PasteSpecial xlPasteValues
DealOffice.PivotTables("PivotTable1").RefreshTable 'Refresh PivotTable on DealOffice Sheet
'Sheet RawData Cleaning
LastCol = RawData.UsedRange.Columns.Count
LastRow = RawData.UsedRange.Rows.Count
RawData.Range(Cells(2, 1), Cells(LastRow, LastCol)).Delete
'Sheet CoverageDealOffice Pivot data copying to RawData
With DealOffice
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
LastCol = .Cells(17, .Columns.Count).End(xlToLeft).Column
.Range(Cells(17, 1), Cells(LastRow - 1, LastCol)).Copy
End With
RawData.Cells(2, 1).PasteSpecial xlPasteValues
'Formatting/other changes & Saving
SFDCReport.Activate
ActiveSheet.Outline.ShowLevels RowLevels:=0, ColumnLevels:=1
ActiveWindow.ScrollColumn = 68
DealOffice.Select
FZ.SaveAs Filename:=DirExport & "\" & CurrDate & "_NCE Deal Office Report_" & SubRegion & ".xlsb", FileFormat:=50
NextIteration:
End If
Next
Thanks guys, Gamca

not sure why this keeps copying whole data set from original to the destination.. I need only filtered data to be copied into Destination, that begins with A13 in the destination sheet SFDCReport
'Filter, Select & Copy filtered data to SFDCReport table
DS.Range("A1").CurrentRegion.AutoFilter Field:=84, Criteria1:=SubRegion
LastRow = DS.AutoFilter.Range.Columns(1).SpecialCells(xlCellTypeVisible).Cells.Count - 1
LastCol = DS.AutoFilter.Range.Columns.Count
Set rTable = DS.AutoFilter.Range
Set rTable = rTable.Resize(rTable.Rows.Count - 1)
Set rTable = rTable.Offset(1) 'Move new range down to start at the first data row
Set rTable2 = SFDCReport.Range(SFDCReport.Cells(13, 1), SFDCReport.Cells(LastRow, LastCol))
rTable2.Value = rTable.Value

Corrected/Solved - Thanks to some advices, I have changed the "syntax" coding to use With/End With + paid attention to include "address" into all Range objects.
part of changed code:
'Filter, Select & Copy filtered data to SFDCReport table
With DS.Range("A1").CurrentRegion
.AutoFilter Field:=84, Criteria1:=SubRegion
.Offset(1).Resize(.Rows.Count - 1).SpecialCells(xlCellTypeVisible).Copy SFDCReport.Cells(13, 1)
End With

Related

Combining Excel Sheets into the summary sheet for specific sheet names

I'm trying to run this code but only for specific worksheet names. the name is as follows "X_Score_" & CurrentDate where CurrentDate changes every time the loop runs. Right now it runs for all worksheets in the whole workbook which is quite messy.
Set wsMaster = ThisWorkbook.Worksheets("XXX_SCORE_TOTAL")
RowTracker = 2
flag = False
For Each bs In ActiveWorkbook.Worksheets
If UCase(bs.Name) <> "XXX_SCORE_TOTAL" Then
LastRow = bs.Cells(Rows.Count, "A").End(xlUp).Row
LastColumn = bs.Cells(1, Columns.Count).End(xlToLeft).Column
End If
bs.Range(bs.Cells(2, 1), bs.Cells(LastRow, LastColumn)).Copy wsMaster.Cells(RowTracker, 1)
RowTracker = RowTracker + LastRow
Next bs
I tried to predifine something like Set MyCollection = ThisWorkbook.Worksheets("X_Score_" & CurrentDate) and then put in in the For loop like For Each bs In MyCollectionbut it didn't worked
If the goal is to process all sheets in the workbook whose names start with "X_Score_", this can be done with Left():
Sub test1()
Set wsMaster = ThisWorkbook.Worksheets("XXX_SCORE_TOTAL")
RowTracker = 2
flag = False
For Each bs In ThisWorkbook.Worksheets ' or ActiveWorkbook?
If Left(UCase(bs.Name), 8) = "X_SCORE_" Then
LastRow = bs.Cells(Rows.Count, "A").End(xlUp).Row
LastColumn = bs.Cells(1, Columns.Count).End(xlToLeft).Column
Set Rng = bs.Range(bs.Cells(2, 1), bs.Cells(LastRow, LastColumn))
Rng.Copy wsMaster.Cells(RowTracker, 1)
RowTracker = RowTracker + Rng.Rows.Count ' shift RowTracker according to the number of rows copied
End If
Next
End Sub

Copy specific range to from one worksheet to another manipulating destinaion address

I have a ressource worksheet I need to have represented in a different format enabling it as data source for Power BI. This is representing the data 'as is' and the format I need it 'to be'.
I have created a VBA script to perform this - it does not work that well... Any suggestions/ideas on how to solve this puzzle? (the real data sheet is 250+ rows and 6-800 columns)
Sub PopulateCells()
Dim rng As Range
Dim rng2 As Range
Dim LastCell As String
Dim Dest As String
Application.ScreenUpdating = False
'Cleans BI worksheet
Ark4.Cells.Delete
'Initialize Row- and Column numbers
Startrow = 4
StartColumn = 7
EndColumn = 18
Ark3.Activate
'Finds adresses and ranges to be used in macro
Set rng = Sheets(Sheets.Count).Cells
lastrow = Last(1, rng)
dColumns = Last(2, rng)
aKol = dColumns
LastCell = Last(3, rng)
Set rng = Parent.Range("G4", LastCell)
Set rng2 = Range(Cells(Startrow, StartColumn), Cells(Startrow, EndColumn))
cColumn = Round(dColumns / 12, 0) 'Total number of columns divided by 12, which equals 1 year
'Finds address on last column with data
sKol = Ark3.Cells(3, Columns.Count).End(xlToLeft).Address
'Initialize a row indicatorvariable + fills out dummy data in the BI worksheet to match the code
Ark4R = 3
Ark4.Range("A1:" & sKol).Value = "x"
' Loop all rows in the datasheet
For I = 4 To lastrow
'Loop all columns in datasheet (in group of 12)
For ii = 1 To cColumn
'Initialize a range (rng2) to see if there is data in the range
Set rng2 = Ark3.Range(Cells(Startrow, StartColumn), Cells(Startrow, EndColumn))
'fills relevant data in the data source sheet
If WorksheetFunction.countA(rng2) <> 0 Then
Ark3.Range("E" & I).Value = rng2.EntireColumn.Cells(1).Value
Ark3.Range("F" & I).Value = rng2.EntireColumn.Cells(1).Offset(1).Value
aRowSource = Ark3.Range(Cells(Startrow, StartColumn), Cells(Startrow, EndColumn)).Row
'Copy to data destination sheet
rng2.EntireRow.Copy 'Copy the entire row
Ark4.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).PasteSpecial xlPasteAll 'Paste entire row to the next empty row in destination sheet
Application.CutCopyMode = False
Ark4.Range(Ark4.Cells(ActiveCell.Row, 7), Ark4.Cells(ActiveCell.Row, aKol)).ClearContents 'Clear hour-registration data in destination sheet
aRowDest = Range(Ark4.Cells(ActiveCell.Row, 7), Ark4.Cells(ActiveCell.Row, aKol)).Row 'Get row number in destionation sheet
Dest = rng2.Address(RowAbsolute:=False, ColumnAbsolute:=False) 'Get the address range of the hour-registration in the source sheet
Dest = Replace(Dest, aRowSource, aRowDest) 'Manipulate the address to match the location in the destination sheet
rng2.Copy Ark4.Range(Dest) 'Copy the range to the destination sheet
Application.CutCopyMode = False
End If
'Counter - takes the next 12 cells = 1 year
StartColumn = StartColumn + 12
EndColumn = EndColumn + 12
Next ii 'Next cColumn
'Make a new row to cater for operation hours (inserted by another procedure)
Ark3.Range(Cells(Startrow, 1), Cells(Startrow, 4)).Copy
Ark4.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).PasteSpecial xlPasteAll
Application.CutCopyMode = False
'Counters
Startrow = Startrow + 1
StartColumn = 7
EndColumn = 18
Next I
End Sub
I found out that I was not referencing the ranges in the two sheet properly. After adding proper referenving the code worked.

How to fix 'Run-time error '1004' PasteSpecial

I have a file (called original) that has partially information for each row. Each row has a file name column (from where information is to be captured from).
For each row I'd like to open up the file in the file name column, and grab information from certain rows.
In the file it is only one column, with rows "Supplier Number : _____", the location of this row is variable, so I'd like to iterate through each row in the file to copy this cell value and paste it into the original file in the corresponding row.
This is what I have so far:
Const FOLDER_PATH = "C:\Users\[user]\Downloads\"
Sub iterateThroughAll()
ScreenUpdating = False
Dim wks As Worksheet
Set wks = ActiveSheet
Dim source As String
Dim target As String
Dim update As String
Dim rowT As Integer
rowT = 2
rowTT = 1
Dim rowRange As Range
Dim colRange As Range
Dim rowRangeT As Range
Dim LastCol As Long
Dim LastRow As Long
Dim LastRowT As Long
LastRow = wks.Cells(wks.Rows.Count, "A").End(xlUp).Row
Set rowRange = wks.Range("A2:A" & LastRow)
'Loop through each row
For Each rrow In rowRange
source = FOLDER_PATH & wks.Cells(i, 18).Value 'the name of the file we want to grab info from in this Column, always populated
'if the cell is empty, search through the file for "Supplier Number : "
If IsEmpty(wks.Cells(rowT, 19)) Then
Set wb = Workbooks.Open(source)
wb.Activate
LastRowT = Cells.Find("*", searchorder:=xlByRows, searchdirection:=xlPrevious).Row
Set rowRangeT = wks.Range("A1:A" & LastRowT)
For Each i In rowRangeT
If InStr(i.Cells.Offset(rowTT), "Supplier") > 0 Then
Range("A" & rowTT).Select
Selection.Copy
Windows("Get Supplier Number.xlsm").Activate
Range("A" & rowT).Select
wks.Paste
Else
rowTT = rowTT + 1
End If
Next i
wb.Close
Next rrow
ScreenUpdating = True
End Sub
I get the pastespecial error 1004.
What is expected is that for each row in "Get Supplier Number.xlsm", the row's A column is updated with the information
Thank you for helping!
First of all you should get rid of Activate and Select methods. You don't have to use them and they give nothing to your code. Using them is not a good approach.
To avoid them you should use specific references. Which you are doing so, until a specific point. Inside the for loop, after setting the wb, replace everything with the following:
With wb.Worksheets(1)
LastRowT = .Cells.Find("*", searchorder:=xlByRows, searchdirection:=xlPrevious).Row
Set rowRangeT = .Range("A1:A" & LastRowT)
For Each i In rowRangeT
If InStr(i.Cells.Offset(rowTT), "Supplier") > 0 Then
.Range("A" & rowTT).Copy wks.Range("A" & rowT)
Else
rowTT = rowTT + 1
End If
Next i
wb.Close
End With
I think this should do the job for you.
PS: If you need just the value of the cell in the opened workbook, then you could replace the Copy line with a simple equality:
wks.Range("A" & rowT) = .Range("A" & rowTT)

Excel formula only bring over row in other worksheet if cell in column A is not blank

I have two worksheets in one Excel workbook, and I only want to take the lines that have data in the cell (from worksheet1 into worksheet2) if Column A has data in it. My formula in worksheet 2 is =IF('Raw Data'!A2<>"", 'Raw Data'!A2,), but I actually don't want it to bring in the row at all if there is no data as shown in Rows 3 and 5. Right now it is bringing the whole row in:
In
you see that it is still bringing the row into worksheet 2 if there is no data. Any ideas how to only bring in the rows with the data?
Sub DataInCell()
Dim rw As Long
rw = 2
' Select initial sheet to copy from
Sheets("Raw Data").Select
' Find the last row of data - xlUp will check from the bottom of the spreadsheet up.
FinalRow = Cells(Rows.Count, 1).End(xlUp).Row
' For loop through each row
For x = 2 To FinalRow
If Cells(x, 1).Value <> 0 Then
Range("A" & x & ":C" & x).Copy
Sheets("Sheet1").Select
NextRow = Cells(Rows.Count, 1).End(xlUp).Row + 1 'Continue incrementing through the rows.
Cells(NextRow, 1).Select ' Find the next row.
ActiveSheet.Cells(NextRow, "A").PasteSpecial xlPasteAll ' Paste information.
Sheets("Raw Data").Select 'Reselect sheet to copy from. Probably uneccessary.
End If
Next x
End Sub
After you update the sheet names on the 3rd and 4th line, you will see that the code carries over the entire row. You can modify using Range(Cells, Cells) if you want partial ranges.
Option Explicit
Sub Non_Blanks()
Dim ms As Worksheet: Set ms = ThisWorkbook.Sheets("Sheet1") '<-- Master Sheet
Dim ns As Worksheet: Set ns = ThisWorkbook.Sheets("Sheet2") '<-- New Sheet
Dim i As Long, MoveMe As Range, LR As Long
For i = 2 To ms.Range("B" & ms.Rows.Count).End(xlUp).Row
If ms.Range("A" & i) = "*" Then
If Not MoveMe Is Nothing Then
Set MoveMe = Union(MoveMe, ms.Range("A" & i))
Else
Set MoveMe = ms.Range("A" & i)
End If
End If
Next i
If Not MoveMe Is Nothing Then
LR = ns.Range("A" & ns.Rows.Count).End(xlUp).Offset(1).Row
MoveMe.EntireRow.Copy
ns.Range("A" & LR).PasteSpecial xlPasteValuesAndNumberFormats
End If
End Sub

use range object as part of a loop

I pasted the entire macro below but this is the important part.
Range("B2:B10000").Value = Range("B2").Offset(-1, 1).Value
Range("D2:D10000").Value = Range("D2").Offset(-1, 1).Value
Range("F2:F10000").Value = Range("F2").Offset(-1, 1).Value
Range("H2:H10000").Value = Range("H2").Offset(-1, 1).Value
It works as is except it is creating unnecessary data because I don't know how to use variable names in a range object. My ranges are currently hard coded such as ("A1:A1000"), when I would like it to be something like ("A1:A & LastRow).
Also I have to explicitly call out column names to copy because the range won't accept a variable name like ("currentColumn & 1:currentColumn & LastRow).
Is there a way to use a varible name as part of a range object so we can use them in loops?
Sub prepareWorkbook()
Dim wbk As Workbook
Set wbk = ThisWorkbook
Dim wks As Worksheet
Set wks = wbk.ActiveSheet
Dim colx As Long
Dim ColumnCount As Long
Dim MySheetName As String
MySheetName = "Import"
LastRow = sht.Cells.Find("*", searchorder:=xlByRows, searchdirection:=xlPrevious).Row
'copy the worksheet and rename it before editing
Sheets(1).Copy After:=Sheets(1)
ActiveSheet.Name = MySheetName
'identify the Id column and move it to 1st column
Dim answer As Variant
Dim IdColumn As Range
answer = Application.InputBox("Enter Letter of Id column")
If Columns(answer).Column = 1 Then
Else
'cut Id column from current location and insert it at column index 1
Columns(answer).Select
Selection.Cut
Columns("A:A").Select
Selection.Insert Shift:=xlToRight
End If
'trim the PartNumber column of any trailing spaces
Dim c As Range
For Each c In Range("A1:A10000")
c.Value = Application.Trim(Replace(c.Value, Chr(160), Chr(32)))
Next
' insert column every other column
' Loop through number of columns.
ColumnCount = Application.WorksheetFunction.CountA(Rows(1)) * 2
'step 2 means skip every other
For colx = 2 To ColumnCount Step 2
Columns(colx).Insert Shift:=xlToRight
Next
Range("B2:B10000").Value = Range("B2").Offset(-1, 1).Value
Range("D2:D10000").Value = Range("D2").Offset(-1, 1).Value
Range("F2:F10000").Value = Range("F2").Offset(-1, 1).Value
Range("H2:H10000").Value = Range("H2").Offset(-1, 1).Value
wks.Cells.EntireColumn.AutoFit
MsgBox ("Done")
End Sub
Assuming the you are running code in the Worksheet added here:
'copy the worksheet and rename it before editing
Sheets(1).Copy After:=Sheets(1)
ActiveSheet.Name = MySheetName
Also not sure what is the purpose of this code, nevertheless using it for the sample
Range("B2:B10000").Value = Range("B2").Offset(-1, 1).Value
Try this:
Dim lLastRow As Long
lLastRow = wbk.Worksheets(MySheetName).UsedRange.SpecialCells(xlLastCell).Row
Rem This updates only columns B, D, F & H - adjust as needed
For colx = 2 To 8 Step 2
With wbk.Worksheets(MySheetName)
Rem Creates Range as Range(Cells(rIni,cIini), Cells(rEnd,cEnd))
rem Corresponding code for "Range("B2:B10000").Value = Range("B2").Offset(-1, 1).Value" (see comment above)
Range(.Cells(2, colx), .Cells(lLastRow, colx)) = .Cells(2, colx).Offset(-1, 1).Value
End With: Next
Something like:
Dim LastRow As Long
LastRow = Cells(Rows.Count, "A").End(xlUp).Row
Range("B2:B" & LastRow).Value = Range("B2").Offset(-1, 1).Value
Range("D2:D" & LastRow).Value = Range("D2").Offset(-1, 1).Value
Range("F2:F" & LastRow).Value = Range("F2").Offset(-1, 1).Value
Range("H2:H" & LastRow).Value = Range("H2").Offset(-1, 1).Value
Although this answer won't be applied to your situation, I feel like this could help answer some questions you have in there.
When specifying a range, you can separate the column (letter) and row (number) and use your own variables.
In a for loop, this could look like
for i = 1 to 100
Range("A" & i).Value = Range("A"&i).Offset(, 1).Value
next
You can also determine the number of the row of the selected cell using:
dim RowNb as long
RowNb = (ActiveCell.Row)
This also applies to columns, and can be used in a loop like I mentionned at the start.
The one thing that was conspicuous by its absence in your description was any mention of the nature of the data in the worksheet. You mentioned A1 briefly but your range value assignments started at row 2 so it may be inferred that row 1 contains column header labels.
Sub prepareWorkbook()
Dim wbk As Workbook, wks As Worksheet
Dim colx As Long
Dim lc As Long, lr As Long
Dim MySheetName As String
Set wbk = ThisWorkbook 'no idea what this does
Set wks = wbk.ActiveSheet 'no idea what this does
MySheetName = "Import"
'no idea what this does or what sht is
'LastRow = sht.Cells.Find("*", searchorder:=xlByRows, searchdirection:=xlPrevious).Row
'copy the worksheet and rename it before editing
Sheets(1).Copy After:=Sheets(1)
With Sheets(2)
.Name = MySheetName
If CBool(Application.CountIf(.Rows(1), "PartNumber")) Then
colx = Application.Match("PartNumber", .Rows(1), 0)
Else
colx = .Range(Application.InputBox("Enter Letter of Id column") & 1).Column
End If
If .Columns(colx).Column > 1 Then
'cut Id column from current location and insert it at column index 1
.Columns(colx).Cut
.Columns(1).Insert Shift:=xlToRight
End If
'quickest way to trim trailing spaces is with Text-to-Columns, Fixed Width
With .Columns(1)
.TextToColumns Destination:=.Cells(1), DataType:=xlFixedWidth, FieldInfo:=Array(0, 1)
End With
' insert column every other column (working backwards toward A1)
For lc = .Cells(1, Columns.Count).End(xlToLeft).Column To 2 Step -1
.Columns(lc).Insert Shift:=xlToRight
Next lc
For lc = (.Cells(1, Columns.Count).End(xlToLeft).Column - 1) To 2 Step -2
'let's put the row-by-row value in instead of a single value into all cells
lr = .Cells(Rows.Count, lc + 1).End(xlUp).Row
With .Cells(2, lc).Resize(lr - 1, 1)
.Cells = .Offset(-1, 1).Value
.EntireColumn.AutoFit
End With
Next lc
End With
Set wbk = Nothing
Set wks = Nothing
End Sub
Explanations as comments in code.

Resources