So I have a macro that cuts and copies "open orders" and inserts those lines below data (See previous post), after that it sticks a header above the open order data. The way the macro is written currently, if there are no open order data it sticks the header all the way down to row 65k.
See code below:
Dim LastRow, NewLast, MovedCount As Integer
LastRow = ActiveSheet.Cells(ActiveSheet.Rows.Count, "A").End(xlUp).Row 'Find last Row
NewLast = LastRow + 1 'NewLast tracks the new last row as rows are copied and pasted at the end
MovedCount = 0
For I = 2 To LastRow
If Left(Cells(I, 4), 1) = "O" Then 'Copy the row, increment NewLast and paste at the bottom.
Rows(I).Cut
'LastRow = LastRow - 1
Cells(NewLast + 3, 1).Select
ActiveSheet.Paste
Rows(I).Delete
I = I - 1 'Since we deleted the row, we must decrement i
MovedCount = MovedCount + 1 'Keeps track of number of rows moved so as not to overshoot the original last line
End If
If I + MovedCount = LastRow Then Exit For 'Exit For loop if we reached the original last line of the file
Next I
'inserts a header for the open section
Cells(1, 1).Select
Selection.End(xlDown).Select
nRowMax = Selection.Row
Selection.Offset(1, 0).Select
Selection.EntireRow.Copy
Selection.End(xlDown).Select
Selection.Offset(-1, 0).Select
Selection.PasteSpecial xlPasteFormats
ActiveCell.Select
ActiveCell = "Open Orders"
Application.CutCopyMode = False
So my question is how can I either keep the header from being copied if there is no open order data or delete the header if there is no data around it.
I was thinking of putting an IF there is no data below header THAN delete header. Sorry if this is somewhat open ended i think there are a couple ways to go about this.
See images below to give you an idea what the data looks like with and without the open orders.
If I'm understanding the question correctly, then if there are no open orders, you don't want the "Open Orders" header to populate at all. You can accomplish this by nesting the entire bottom section of code in an if statement:
If MovedCount <> 0 Then
Cells(1, 1).Select
...
Application.CutCopyMode = False
End If
Related
I'm trying to run a code that will search through a column, find keywords, then copy and paste those rows into another sheet. Unfortunately, when I run the code step-by-step I can see that the first time it attempts to copy and paste a row, it copies the active cell and pastes that value across the row in the next sheet, and disregards the "If Then" statement searching for the keywords. After it pastes the active cell value it works fine and pastes the correct rows, but I can't figure out why it pastes the active cell first.
Sub CompletedJob()
'Looks through the status column (N) of the Projects Overview table and moves them to Completed table, then deletes row from projects list
Dim Firstrow As Long
Dim lastRow As Long
Dim LrowProjectsOverview As Long
With Sheets("Projects Overview")
.Select
Firstrow = .UsedRange.Cells(1).Row
lastRow = .UsedRange.Rows(.UsedRange.Rows.Count).Row
For LrowProjectsOverview = lastRow To Firstrow Step -1
With .Cells(LrowProjectsOverview, "N")
If Not IsError(.Value) Then
If ((.Value = "Complete - Design") Or (.Value = "P4P") Or (.Value = "Ready for Setup")) Then .EntireRow.Select
Selection.Copy
Range("A600:Q600").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
If Sheet9.Range("B2").Value = "" Then
Sheet9.Range("A2:Q2").Value = Sheet1.Range("A600:Q600").Value
Sheet1.Range("A600:Q600").ClearContents
Else
Sheet9.Range("B2").EntireRow.Insert
Sheet9.Range("A2:Q2").Value = Sheet1.Range("A600:Q600").Value
Sheet1.Range("A600:Q600").ClearContents
Sheet9.Range("B2:Q2").Interior.Color = xlNone
Sheet9.Range("B2:Q2").Font.Bold = False
Sheet9.Range("B2:Q2").Font.Color = vbBlack
Sheet9.Range("B2:Q2").RowHeight = 14.25
End If
If Sheet9.Range("B2").Value = "" Then
Sheet9.Range("B2").EntireRow.Delete
End If
If ((.Value = "Complete - Design") Or (.Value = "P4P") Or (.Value = "Ready for Setup")) Then .EntireRow.Delete
End If
End With
Next LrowProjectsOverview
End With
End Sub
I tried to recreate your problem. My code is not a direct solution for you. You need to adapt it to your problem. This is important because this is how you learn to code.
I tried my very best to comment my code as heavily as possible. I am not referencing sheets, please add this since you are trying to copy from one sheet to another.
I don't need any select statement.
This is my vba code.
Option Explicit
Sub SearchKeyandCopy()
Dim LastLine As Long
Dim i As Long
Dim j As Long
'Find Number of Rows in Status column (column D)
LastLine = Columns("D").Find("*", , , , xlByColumns, xlPrevious).Row
'Set row where it should start pasting
j = 2
'Iterate over all cells with status
For i = 2 To LastLine
'Check if the Keyword (Key) is in Status column
'InStr returns the position and 0 if not found
'code checks if position is different from 0
If InStr(Cells(i, "D").Value, "key") <> 0 Then
'Copy values
Range(Cells(i, "A"), Cells(i, "D")).Copy Destination:=Range(Cells(j, "F"), Cells(j, "I"))
'increase counter for where to paste
j = j + 1
End If
Next i
End Sub
This is how it looks before running the code
This is how it looks after running the code
I'm working on a formatting project for a monthly template. The data in column "E" will be static in each work book but different in other workbooks I'll run the macro on. IE one workbook may have 10K rows in column "E" and another workbook could have 20K in column "E". I need to copy that block of text below its self 2x. So I have a triplication of all that data from "E2:E".
I'm not looking for HUGE solutions with a million unnecessary Dimed variables. I'm close. What am I missing?
Range(Range("E2"), Range("E2").End(xlDown)).Select
Selection.Copy
Cells(Cells(Rows.Count, 1).End(xlUp).Row + 1, 1).Paste<------ ERROR!
Becoming frustrated.
Using < 1million variables...
With ActiveSheet
With .Range(.Range("E2"), .Cells(.Rows.Count, "E").End(xlUp))
.Copy .Offset(.Rows.Count, 0)
.Copy .Offset(.Rows.Count * 2, 0)
End With
End With
Compared to #Tim-Williams answer, this feels positively hideous. However, I present to you:
Range(Range("E2"), Range("E2").End(xlDown)).Copy
For idx = 1 To 2
Cells(Range("E2").End(xlDown).Row + 1, "E").Select
ActiveSheet.Paste
Next
the following is almost there:
Application.CutCopyMode = False
Range(Range("E2"), Range("E2").End(xlDown)).Select
Selection.Copy
I just need it to drop down 1 and paste that, THEN drop to the NEXT blank row and paste it again.
my 0.02 cents
Range.Value approach (pasting values only)
With Range("E2", Cells(Rows.Count, "E").End(xlUp))
.Offset(.Rows.Count).Value = .Value
.Offset(.Rows.Count * 2).Value = .Value
End With
formula approach (and pasting values only)
With Range("E2", Cells(Rows.Count, "E").End(xlUp))
.Offset(.Rows.Count).Resize(.Rows.count * 2).FormulaR1C1 = "=R[" & -.Rows.Count & "]C" '<--| have 2x referenced range cells below it with its values
.Resize(.Rows.Count * 2).Value = .Resize(.Rows.Count * 2).Value '<--| get rid of formulas
End With
Copy/PasteSpecial approach (you can choose what to paste - see PasteSpecial() method)
With Range("E2", Cells(Rows.Count, "E").End(xlUp))
.Copy
.Offset(.Rows.Count).Resize(.Rows.Count * 2).PasteSpecial ' you have some options like xlPasteAll (pastes all) or xlPasteValues (pastes values only)and others
Application.CutCopyMode = False '<--| this to free clipboard and clear highlighted cells
End With
I'm new to vba and need a little help. I have a sheet named "Archive" which will have 12 sets of data displayed/structured in somewhat of a table format. My goal is to pull data from other sheets within the same workbook and paste it in a specific range that corresponds to the appropriate "table" for that data. Here is my code for data that is being pulled from a sheet named "Daily DB" and is being pasted to the "Archive" sheet.
Sub GetDailyDataByWeek()
Dim cw As Integer ' current week
Dim lr As Long 'last row of data
Dim i As Long ' row counter
'Clear exsisting contents
Worksheets("Archive").Range("A5:E11").ClearContents
'Get week number and year of current date
cw = Format(Date, "ww")
With Worksheets("Daily DB")
' Find last row of data
lr = .Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
For i = 2 To lr
If Format(.Cells(i, 1).Value, "ww") = cw Then
.Range(.Cells(i, 1), .Cells(i, 5)).Copy
Worksheets("Archive").Range("a" & Rows.Count).End(xlUp).Offset(1, 0).PasteSpecial xlPasteFormulasAndNumberFormats
End If
Next i
End With
Application.CutCopyMode = False
End Sub
This code does what I want it to do. The line that I need help in fixing is:
Worksheets("Archive").Range("a" & Rows.Count).End(xlUp).Offset(1, 0).PasteSpecial xlPasteFormulasAndNumberFormats
As this line looks for the last row of data, which in my case would be the header row of the 12th table. However, I'd like this particular data to go into the first table which after the header row starts at "A5", but I'm not sure how to go about that. Any and all help is greatly appreciated.
If you want to replicate the data from another cell or range into the same workbook I would use the "Value" method of the Range object, like this:
Worksheets("Archive").Range("A" & i).Value = Worksheets("XXX").Range("Z" & j).Value
By doing it like this you would avoid doing all the copy and paste operations.
If you dont want to specify a Range for each value, you could activate the firs cell of the first row and then "offset" your way through, like this:
Worksheets("Archive").Range("A" & i).Activate
ActiveCell.Value = blah blah blah
ActiveCell.Offset(1, 0).Activate 'If you want to move to the next row (same column)
ActiveCell.Offset(0, 1).Activate 'If you want to move to the next column (Same row)
I have one workbook with two sheets. Sheet 1 is laid out to look like a form with a submit button and named TravelRequest. Sheet 2 is just a database that is collected from sheet 1 and named TravelLog.
Here is how it works now:
User on Sheet 1 fills out the proper sections of the Excel form
User clicks on the Submit button
Data gets copied onto Sheet 2 in its own columns all in 1 row and clears Sheet 1 entries
When the next user fills out the form it should add a new ROW in Sheet 2
So, right now my script copies one cell to another specified cell and I tried many different codes from this website but cant seem to get any to work, also my copy script is hardcoded copy & paste operations. I don't know how to work around that.
I can upload the Excel sheet somewhere if anyone needs it for helping out here.
Sub Submit()
Application.ScreenUpdating = False
Range("L5").Copy
Sheets("TravelLog").Range("B6").PasteSpecial xlPasteValues
Range("C5").Copy
Sheets("TravelLog").Range("C6").PasteSpecial xlPasteValues
Range("G5").Copy
Sheets("TravelLog").Range("D6").PasteSpecial xlPasteValues
Range("c10").Copy
Sheets("TravelLog").Range("E6").PasteSpecial xlPasteValues
Range("c9").Copy
Sheets("TravelLog").Range("F6").PasteSpecial xlPasteValues
Range("I9").Copy
Sheets("TravelLog").Range("G6").PasteSpecial xlPasteValues
Range("I10").Copy
Sheets("TravelLog").Range("H6").PasteSpecial xlPasteValues
Range("C13").Copy
Sheets("TravelLog").Range("I6").PasteSpecial xlPasteValues
Range("C14").Copy
Sheets("TravelLog").Range("J6").PasteSpecial xlPasteValues
Range("C15").Copy
Sheets("TravelLog").Range("K6").PasteSpecial xlPasteValues
Range("C16").Copy
Sheets("TravelLog").Range("L6").PasteSpecial xlPasteValues
Range("C17").Copy
Sheets("TravelLog").Range("M6").PasteSpecial xlPasteValues
Range("C18").Copy
Sheets("TravelLog").Range("N6").PasteSpecial xlPasteValues
Range("i13").Copy
Sheets("TravelLog").Range("O6").PasteSpecial xlPasteValues
Range("i14").Copy
Sheets("TravelLog").Range("P6").PasteSpecial xlPasteValues
Range("i15").Copy
Sheets("TravelLog").Range("Q6").PasteSpecial xlPasteValues
Range("i16").Copy
Sheets("TravelLog").Range("R6").PasteSpecial xlPasteValues
Range("i17").Copy
Sheets("TravelLog").Range("S6").PasteSpecial xlPasteValues
Range("h20").Copy
Sheets("TravelLog").Range("W6").PasteSpecial xlPasteValues
Application.ScreenUpdating = True
End Sub
* EDIT *
With druciferre's answer, I'm getting this error
ERROR OVERFLOW
on this line
Worksheets("TravelLog").Range(Dest).Value = Worksheets("TravelRequest").Range(Field).Value
Here is the updated refTable array.
refTable = Array("B = L5", "C = C5", "D=G5", "E=C10", "F=C9", "G=I9", "H=I10", "I=C13", "J=C14", "K=C15", "L=C16", "M=C17", "N=C18", "O=I13", "P=I14", "Q=I15", "R=I16", "S=I17", "W=H20")
Try this...
Dim refTable As Variant, trans As Variant
refTable = Array("B = L5", "C = C5", "D=G5", "E=C10", "F=C9")
Dim Row As Long
Row = Worksheets("TravelLog").UsedRange.Rows.Count + 1
For Each trans In refTable
Dim Dest As String, Field As String
Dest = Trim(Left(trans, InStr(1, trans, "=") - 1)) & Row
Field = Trim(Right(trans, Len(trans) - InStr(1, trans, "=")))
Worksheets("TravelLog").Range(Dest).value = Worksheets("TravelRequest").Range(Field).value
Next
In the refTable array, each item is a translation of the form field to the destination column. So, if L5 from the form is supposed to go column B on the log, then you write B = L5. The code can handle with the spaces or without.
I have 3 Sheets: Work, Bill, and Cust. Cust column A contains my unique customers, which I then paste onto cell A3 on the Work sheet where it runs its calculations and then paste it on to the Bill sheet. I then take the next value on the Cust sheet and i paste it back to Work, run the calculation and paste it below the previous set on the Bill sheet. I have 2 questions.
Why isn't my loop working? I'm trying to keep going until I run out of customers on the cust sheet?
Why is it that I can use the custom range BillPlace in the first part of my code, yet I actually have to refer to the cells in the later parts?
Thanks in advance
Sub test1()
Dim WorkPlace As Range, BillPlace As Range, WorkProd As Range
Set WorkPlace = Sheets("Work").Cells(3, 1)
Set BillPlace = Sheets("Bill").Cells(3, 1)
Set WorkProd = WorkPlace.CurrentRegion
WorkPlace.CurrentRegion.Copy
BillPlace.PasteSpecial xlPasteAll
Sheets("Cust").Select
Cells(1, 1).Copy
WorkPlace.PasteSpecial xlPasteAll
WorkProd.Copy
Sheets("Bill").Select
Range("A3").Select
Selection.End(xlDown).Select
Selection.Offset(1, 0).PasteSpecial xlPasteAll
Sheets("Cust").Select
Cells(2, 1).Select
Selection.Offset(1, 0).Select
Do
ActiveCell.Offset(1, 0).Copy
WorkPlace.PasteSpecial xlPasteAll
WorkProd.Copy
Sheets("Bill").Select
Range("A3").Select
Selection.End(xlDown).Select
Selection.Offset(1, 0).PasteSpecial xlPasteAll
Loop Until IsEmpty(ActiveCell.Offset(1, 0))
End Sub
#Portland Runner has a point about using a For Each / Next loop. By doing that you can probably eliminate the counters and a bunch of selecting from your working code above, removing a bunch of complexity from your process.
The principle of a For/Next loop is easy enough: define TheLargerRange containing the cells you will loop through. Define a SingleCell range to contain the current cell you are working with. Then you can start the loop saying something like:
For Each SingleCell in TheLargerRange
'~~> your loop actions go here
Next SingleCell
Also, you can do a lot without selecting specific locations in your workbook. Instead copy, paste, or assign values by just referencing the location. If you want, you can set variables to make this easier in longer code.
The following example just moves a column of customer data from one sheet to another, as an example of how to use the For Each / Next loop structure and how to avoid selecting everything you work with. There is only one selection in this code, and that is only because the compiler chokes if you use End(xldown) to attempt setting a range on an unselected tab. Otherwise there could be no selections.
Sub UsingForNextAndAvoidingSelections()
'~~> Set variables for referencing the "Cust" tab
Dim CustomerList As Range
Dim Customer As Range
Dim CustomerTab As Worksheet
Set CustomerTab = Sheets("Cust")
CustomerTab.Select
Set CustomerList = CustomerTab.Range("A1", Range("A1").End(xlDown))
'~~> Set variables for referencing the "Bill" tab
Dim BillTab As Worksheet
Dim BillRow As Range
Set BillTab = Sheets("Bill")
Set BillRow = BillTab.Range("A1")
'~~> Loop through the customer list, copying each value to the new BillRow location
For Each Customer In CustomerList
Customer.Copy
BillRow.PasteSpecial xlPasteAll
Set BillRow = BillRow.Offset(1, 0)
Next Customer
End Sub
12/27/2013: I just realized why the code Set CustomerList = CustomerTab.Range("A1", Range("A1").End(xlDown)) was throwing an error when CustomerTab was not selected: I forgot to fully qualify the second range statement in that line: Range("A1").End(xlDown).
I believe that if you qualify that line of code like this Set CustomerList = CustomerTab.Range("A1", CustomerTab.Range("A1").End(xlDown)) you can eliminate the CustomerTab.Select that precedes it and conduct the entire process without a single Select.
WorkProd.Copy
Sheets("Bill").Select
Range("A3").Select
Selection.End(xlDown).Select
Selection.Offset(1, 0).PasteSpecial xlPasteAll
Loop Until IsEmpty(ActiveCell.Offset(1, 0))
You are going to the end of a column and pasting one row further down. You then check if the cell one row further down is empty, but it won't be because you've just pasted into it. This is why it repeats endlessly.
I assume you should be looking for an empty cell somewhere other than one row below the current cursor position.
HA! i fixed it. This isn't the most orthodox approach but it worked. Oh pardon me but i did it in production so the name of the sheets and cell positions changed slightly. CountC is a helper cell that counts the number of customers. Thanks everyone for your help.
Sub Pull_Billing()
Dim WorkPlace As Range, BillPlace As Range, WorkProd As Range, PlaceHolder As Range, CountC As Integer, n As Integer
Set WorkPlace = Sheets("Work").Cells(3, 1)
Set BillPlace = Sheets("ABS_Billing_Sheet").Cells(3, 1)
Set WorkProd = WorkPlace.CurrentRegion
CountC = Sheets("CTA_Info").Cells(1, 5).Value
Sheets("CTA_info").Cells(2, 2).Copy
WorkPlace.PasteSpecial xlPasteAll
WorkPlace.CurrentRegion.Copy
BillPlace.PasteSpecial xlPasteAll
Sheets("CTA_Info").Select
Cells(3, 2).Copy
WorkPlace.PasteSpecial xlPasteAll
WorkProd.Copy
Sheets("ABS_Billing_Sheet").Select
Range("A3").Select
Selection.End(xlDown).Select
Selection.Offset(1, 0).PasteSpecial xlPasteAll
Sheets("CTA_Info").Select
Cells(4, 2).Select
n = ActiveCell.Row
Do
Cells(n, 2).Select
Selection.Copy
WorkPlace.PasteSpecial xlPasteAll
WorkProd.Copy
Sheets("ABS_Billing_Sheet").Select
Range("A3").Select
Selection.End(xlDown).Select
Selection.Offset(1, 0).PasteSpecial xlPasteAll
Sheets("CTA_Info").Select
Cells(n + 1, 2).Select
n = ActiveCell.Row
Loop Until n > CountC + 2
Sheets("CTA_info").Cells(2, 2).Copy
WorkPlace.PasteSpecial xlPasteAll
Sheets("ABS_Billing_Sheet").Select
End Sub