Title isn't the best so here a an overview.
I'm using VBA to copy select columns from one workbook to another, as what will be part of a larger automated program.
On the Workbook I am copying from, there are different sheets containing a "Stock Number" column. When pasting into my other workbook, I am trying to get these columns to merge into 1 single column (pasting below the last entry from the first sheet and so on).
Here is my current code:
Sub import_adam_article()
Windows( _
"copyfrom.xlsx" _
).Activate
Columns("F:G").Select
Selection.Copy
Windows("pasteinto.xlsx").Activate
Columns("A:A").Select
ActiveSheet.Paste
Windows( _
"copyfrom.xlsx" _
).Activate
Columns("N:N").Select
Application.CutCopyMode = False
Selection.Copy
Windows("pasteinto.xlsx").Activate
Columns("C:C").Select
ActiveSheet.Paste
Rows("1:1").Select
Selection.Delete Shift:=xlUp
NextRow = Range("A1").End(xlDown).Row + 1
Windows( _
"copyfrom.xlsx" _
).Activate
Columns("F:G").Select
Selection.Copy
Windows("pasteinto.xlsx").Activate
Range("A" & (NextRow)).Select
ActiveSheet.Paste
[A:C].Select
With Selection
.NumberFormat = "General"
.Value = .Value
End With
End Sub
The difficulty is that the amount of Stock Numbers will change every new file that comes through, so it needs to be able to adjust to varying amounts.
I can't seem to find a way to make it work and I've tried searching for answers elsewhere.
EDIT: The current issue with the code that it is selecting the next empty row to paste into, but only that cell, not a variable length down as required by the copyfrom column.
Related
I'm very new to VBA. I used the "Find & Select" option in Excel to find cells (in column A) containing a certain text, then I used CNTRL A and CNTRL C to select all the matching cells in the column, and finally selected a cell in another workbook where I wanted to copy the selected cells. Of course it works when done manually but later, when I run the macro on a new sheet, it gets stuck. Below is what the code looks like - it seems to err at line 4 "ActiveSheet.Paste".
A few notes:
Column A is the column containing data I'm using to find & select from
L5 is one of the cells I select to paste cells found/selected (trying to paste other selections in I5, o5, o12, o26, o40, and o53
"HS" in Line 11 and later "602" are two of seven search criteria used in "find & select". Interesting 5 of the search criteria I used don't show up in coding.
Line 4
Error message includes "Runtime error '1004':
You can't paste this here because the Copy area and paste area aren't the same size.
Select one cell in the paste area (which I think I did when building the macro) or an area that's the same size and try pasting again.
When I click "debug" in the pop-up error message box, it highlights Line 4.
Next, see Line 11. I was doing the same function and yet it says "Selection."... with a much longer description of the selection criteria. I tried moving Lines 10-15 above line 4, to test what this different coding would do. It failed as well
Error message: "Run-time error '91':
Object variable or With block variable not set
Thanks for any help you all can offer! Much appreciated!
Columns("A:A").Select.
Selection.Copy
Range("L5").Select
ActiveSheet.Paste
Columns("A:A").Select
Application.CutCopyMode = False
Selection.Copy
Range("I5").Select
ActiveSheet.Paste
Columns("A:A").Select
Selection.Find(What:="HS", After:=ActiveCell, LookIn:=xlFormulas2, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False).Activate
Application.CutCopyMode = False
Selection.Copy
Range("O5").Select
ActiveSheet.Paste
Columns("A:A").Select
Application.CutCopyMode = False
Selection.Copy
Range("O12").Select
ActiveSheet.Paste
Columns("A:A").Select
Range("A17").Activate
Application.CutCopyMode = False
Columns("A:A").Select
Range("A93").Activate
Selection.Copy
Range("O26").Select
ActiveSheet.Paste
Range("O26:O37").Select
Application.CutCopyMode = False
Selection.Copy
Application.CutCopyMode = False
Selection.Cut
Application.CutCopyMode = False
Selection.ClearContents
Columns("A:A").Select
Range("A21").Activate
Selection.Copy
Range("O40").Select
ActiveSheet.Paste
Selection.Find(What:="602", After:=ActiveCell, LookIn:=xlFormulas2, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False).Activate
Application.CutCopyMode = False
Selection.ClearContents
Columns("A:A").Select
Range("A28").Activate
Selection.Copy
Range("O53").Select
ActiveSheet.Paste
I am at a loss as to what to try to correct the problem(s).
I am sure there is space where I am trying to paste the cells. It works very smoothly when I am doing it manually ;-) But somehow, the coding isn't picking up what I'm doing.
I see suggestions we should avoid "Select" in coding but I'm at a loss what to replace it with, especially given I'm not trying to copy a range but rather only cells in that range matching a criteria.
Two or three things (beside what Ike is recommending you in the comments, recommendation that should be considered):
What gives you an error in line 4 is that you are trying to paste an entire column in a space smaller. It would only work if you paste it in the first cell of the column. I'm sure if you delete that row, it will give you the same error in other similar "activesheet.paste".
It's better to stop using the "range" method for referring to only one cell. Some methods only work using "cells(2, 3)" for cell C2, for example. It's easier to use variables as well with this.
Instead of using the "find" method, try using a combination of a for loop and an "if statement".
Here some examples:
'For declaring variables
Dim I as long
Dim Ro as long
Dim Tex as string
'For finding the last cell with content in column A
Ro = Cells(Rows.Count, 1).End(xlUp).Row
'This declares the text you are looking in the cells value
Tex = "HS"
'Now the loop, that will go from I = whatever value you want to the value limit you give, which in this case will be the last row, "Ro"
For I = 1 to Ro
'Here the "if" conditional, that will do something as long as the condition is met
if InStr(cells(I, 1), Tex) > 0 then 'InStr is a method that gives you the position of a text in the value of a cell, resulting in 0 if can't be found in said value (in this case, the cell in column A and every row from 1 to I)
Cells(I, 12) = cells(I, 1)
end if
next I
And finally, you can repeat this code for "602", or just add it to the "if" statement adding more string variables:
Dim Tex2 as string
Tex2 = "602"
and then...
if InStr(cells(I, 1), Tex) > 0 or InStr(cells(I, 1), Tex2) > 0 then
Let me know if it works
Working on a function to put the filename in a specific column (P) of a file. I've got this running if I specify the cells to put the filename in (e.g. P1:P5).
However, I want to get this to run in the P column, but for all rows that have data in the A column.
I know I could do it for just the whole P column, but i dont want it to run on empty rows (they're of no use)
Code I have so far:
Sub Save_files()
Cells.Select
Selection.Copy
Workbooks.Add
ActiveSheet.Paste
Rows("1:3").Select
Application.CutCopyMode = False
Selection.Delete Shift:=xlUp
Range("P2").Select
ActiveCell.FormulaR1C1 = "=CELL(""filename"")"
Range("P2").Select
Selection.Copy
Range("p1:p5").Select
ActiveSheet.Paste
Application.CutCopyMode = False
Range("D4").Select
End Sub
I want to replace Range("p1:p5").Select with something that selects every P cell that is on a row with data in A of the same row.
Things to note:
Column A will always have data
Columns B through to O may or may not have data
Thanks in advance!
I changed:
Range("p1:p5").Select
to:
LastRow = Cells(Rows.Count, "A").End(xlUp).Row
Range("p1:p" & LastRow).Select
Hi and thanks for your help.
I've two Excel files, lets call them Excel 1 (active one), and Excel 2 (which I just need to compare if there's duplicates).
I want to remove the matches from Excel 1 that are found in Excel 2. Only deleting the matches from Excel 1, and keeping the Excel 2 intact.
I normally do this process with a Vlookup then delete the matches.
[Example][1]: =VLOOKUP(C2,'[End Use Screening Log.xlsb]EUS Log'!$A:$A,1,0))
This is the macro code produced after the Vlookup:
Sub Testing()
'
' Testing Macro
'
'
Workbooks.Open Filename:= _
"Z:\Customer Screening\End User Screening Log\End Use Screening Log.xlsb"
Windows("Copy of WW33 TEST .xlsm").Activate
Range("G2").Select
ActiveCell.FormulaR1C1 = _
"=VLOOKUP(RC[-4],'[End Use Screening Log.xlsb]EUS Log'!C1,1,0)"
Range("G2").Select
Selection.AutoFill Destination:=Range("G2:G16")
Range("G2:G16").Select
Range("G1").Select
Selection.AutoFilter
ActiveSheet.Range("$A$1:$Q$16").AutoFilter Field:=7, Criteria1:=Array( _
"4997466", "6392634", "9026175", "9362935", "9363654", "9369599", "9370171"), _
Operator:=xlFilterValues
Range("A2").Select
Range(Selection, Selection.End(xlDown)).Select
Range(Selection, Selection.End(xlToRight)).Select
Rows("2:2").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Delete Shift:=xlUp
Range("E15").Select
Selection.AutoFilter
Range("G2:G9").Select
Selection.ClearContents
Range("Q2").Select
End Sub
However, I'm trying to automatize the process to do it just with one click.
I want to compare column C from Excel 1 against column A from Excel 2.
I guess I'd need to do it with a VBA, because I've tried it recording the macro but doesn't work properly.
Any ideas how to make this possible?
Maria
I created a very crude code that might just work for your needs. I do not know what your worksheets look like and what your exact needs are but I just assumed you're just matching each cell of column C of Excel 1 to the values at column A of Excel 2, and if there is a match, the cell at row C of Excel 1 will be deleted.
Excel1 Workbook:
Excel2 Workbook:
Code:
Sub Macro1()
Start = 2
'Change path to your excel's file name
'This will open your 2nd excel file so that you won't have to open it evertime. Delete when not needed
Workbooks.Open ("C:\Users\Pops\Desktop\Excel2.xlsm")
'The deletion of the row will mess up with the For-Next loops so I included a GoTo so this is where it will end up
ReLoop:
'Counts how many rows are in your worksheets
Total_rows_Excel1 = Workbooks("Excel1.xlsm").Worksheets("Sheet1").Range("C" & Rows.Count).End(xlUp).Row
Total_rows_Excel2 = Workbooks("Excel2.xlsm").Worksheets("Sheet1").Range("A" & Rows.Count).End(xlUp).Row
'Loops on all the rows on your worksheet
For i = Start To Total_rows_Excel1
For j = 2 To Total_rows_Excel2
If Workbooks("Excel1.xlsm").Worksheets("Sheet1").Range("C" & i) = Workbooks("Excel2").Worksheets("Sheet1").Range("A" & j) Then
Workbooks("Excel1").Worksheets("Sheet1").Rows(i).Delete Shift:=xlUp 'Deletes the rows in Excel1 that have a match from Excel2
Start = i 'This will let the loop to start at the last row it stopped when it loops again so it's less computationally taxing
GoTo ReLoop
End If
Next j
Next i
End Sub
So at the click of a button, all the matches in Excel 1's column C to Excel 2's column A will be removed.
Result:
I've managed to put together a VBA script to automate the concatenating of strings in adjoining columns for the purpose of working with a Python/Applescript tool I've programmed for assisting with renaming of thousands of pdfs files.
There are four columns being worked on.
Col A - an article number for a particular computer in the organisation. 5 digits
Col B - the manufacturer's serial number for a given article number. Several digits long, but only the first 12 are important.
Col C - has a CONCATENATE function to derive the original name of a given PDF file related to a given serial number. "=CONCATENATE(LEFT(B2,12)&".pdf")"
Col D - has another CONCATENATE to help to define the new name of the PDF. "=CONCATENATE(A2&"-"&LEFT(B2,12)&".pdf")"
An example of what I am talking about...
"DMPQ44VZF4YD.pdf" gets renamed to "45872-DMPQ44VZF4YD.pdf"
I've recored a macro to record my using the CONCATENATE functions in cols C and D, then using autofill to drag that down manually to the bottom of the spreadsheet, then copying and pasting those (by value) to columns E and F and then deleting the columns A - D (inclusive) to leave behind only what I want. A messy way of doing things but it gets the job done.
Each Excel file can have a differing number of records/rows. I've arbitrarily set it to 1500 items in the VBA script. Please take a look...
Sub Macro1()
Macro1 Macro
Range("C2").Select
ActiveCell.FormulaR1C1 = "=CONCATENATE(LEFT(RC[-1],12)&"".pdf"")"
Range("C2").Select
Selection.AutoFill Destination:=Range("C2:C1500"), Type:=xlFillDefault
Range("C2:C174").Select
Range("D179").Select
ActiveWindow.SmallScroll Down:=-364
Range("D2").Select
ActiveCell.FormulaR1C1 = "=CONCATENATE(RC[-3]&""-""&LEFT(RC[-2],12)&"".pdf"")"
Range("D2").Select
Selection.AutoFill Destination:=Range("D2:D1500"), Type:=xlFillDefault
Range("D2:D174").Select
ActiveWindow.SmallScroll ToRight:=-2
ActiveWindow.SmallScroll Down:=-528
Columns("C:D").Select
Selection.Copy
Columns("F:F").Select
Selection.PasteSpecial Paste:=xlValues, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=False
Columns("A:E").Select
Application.CutCopyMode = False
Selection.Delete Shift:=xlToLeft
Rows("1:1").Select
Selection.Delete Shift:=xlUp
Range("D5").Select
Dim Rng As Range
For Each Rng In ActiveSheet.UsedRange
If Rng.Value2 = ".pdf" Or Rng.Value2 = "-.pdf" Then Rng.ClearContents
Next Rng
End Sub
It works well but can take a while to process (due to the arbitrarily high number of possible records in a given sheet, perhaps as well as the 'for' loop at the end to get rid of any trailing ".pdfs" and "-.pdfs" that are a hangover from otherwise empty cells affected by the CONCATENATE function). Is there any way of making the more efficient when dealign with a small number of records or perhaps making it easily more scalable?
Here is a link to the code if that helps.
Thanks once again.
Will
You may give this a try...
Sub RenamePDFFiles()
Dim lr As Long
lr = Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
With Application
.Calculation = xlCalculationManual
.EnableAutoComplete = False
.ScreenUpdating = False
End With
Range("C2:C" & lr).Formula = "=IF(B2="""","""",LEFT(B2,12)&"".pdf"")"
Range("C2:C" & lr).Value = Range("C2:C" & lr).Value
Range("D2:D" & lr).Formula = "=IF(AND(A2="""",B2=""""),"""",A2&""-""&LEFT(B2,12)&"".pdf"")"
Range("D2:D" & lr).Value = Range("D2:D" & lr).Value
Columns("A:B").Delete
With Application
.Calculation = xlCalculationAutomatic
.EnableAutoComplete = True
.ScreenUpdating = True
End With
End Sub
For formula in column D, I have used AND function for the logical test so that if both columns A and B are empty, the corresponding cell in column D will also be empty. If required, change it to OR condition.
I am using a macro that creates a copy of a worksheet then renames it, deletes some columns and inserts a formula into a cell and then drags it down.
The part that drags it down does not work!
Sub filterData()
'
' filterData Macro
' Filter data
'
' Keyboard Shortcut: Ctrl+m
'
Sheets("devices").Select
Sheets("devices").Copy After:=Sheets(1)
Sheets("devices (2)").Select
Sheets("devices (2)").Name = "filterData"
ActiveWorkbook.Save
Columns("G:J").Select
Selection.Delete Shift:=xlToLeft
Columns("H:AA").Select
Selection.Delete Shift:=xlToLeft
ActiveWorkbook.Save
Range("G2").Select
ActiveCell.FormulaR1C1 = _
"=LEFT(devices!RC[4],IFERROR(SEARCH("""""""",devices!RC[4]),SEARCH(""-"",devices!RC[4]))-1)"
ActiveWorkbook.Save
Range("G2").Select
Selection.AutoFill Destination:=Range("Table122[Display]")
Range("Table122[Display]").Select
End Sub
As you can see, the part that drags the formula down to last populated cell is not working!!!
Update
I have added the following to the code as well and it still does not work;
lastrow = Range("G2").End(xlUp).Row --new line
Range("G2").Select
ActiveCell.FormulaR1C1 = _
"=LEFT(devices!RC[4],IFERROR(SEARCH("""""""",devices!RC[4]),SEARCH(""-"",devices!RC[4]))-1)"
Range("G2").Select
Selection.AutoFill Destination:=Range("G2:G" & lastrow) --new line
Since it's a Table (VBA ListObject) you can fill in the whole ListColumn at once:
ActiveCell.ListObject.ListColumns("Display").DataBodyRange.Formula = _
"=LEFT(devices!RC[4],IFERROR(SEARCH("""""""",devices!RC[4]),SEARCH(""-"",devices!RC[4]))-1)"
Also, note that you can get rid of the Select statements generated by the Macro Recorder. For example:
Columns("G:J").Select
Selection.Delete Shift:=xlToLeft
can be just:
Columns("G:J").Delete Shift:=xlToLeft
And one final tip is to fully qualify ranges, e.g.:
Worksheets("filterData").Columns("G:J").Delete Shift:=xlToLeft
I'll stop now since you already accepted this answer. Except to say I do like the animation!
The problem with your macro is probably this line:
Range("Table122[Display]").Select
You are trying to auto-fill the Display column, including the Header row, which it probably doesn't like. Try it like this instead:
Range("Table122[[#Data],[Display]]").Select
For a simple solution to macro for dragging formula down to dynamic row count:
You can also use the previous column for a reference of how many rows you want to drag the formula.
Generic: Range("B2:B" & Range("A65000").End(xlUp).Row).FormulaR1C1 = "{=formulahere}"
So in your case it would look something like:
Range("G2:G" & Range("F65000").End(xlUp).Row).FormulaR1C1 = "=LEFT(devices!RC[4],IFERROR(SEARCH("""""""",devices!RC[4]),SEARCH(""-"",devices!RC[4]))-1)"