I am using VBA to copy and paste a variable number of rows from one sheet to another when they meet a criteria.
This is working. However, when the data is pasted into the target sheet the column and row width change to be the same as the source sheet.
How can I stop this from happening? So that just the data is pasted, without the cell formatting.
If anyone knows it would be much appreciated.
Heres the code I'm using.
Sub copyOverdue()
Dim cell As Range
Dim j As Integer
Dim Source As Worksheet
Dim Target As Worksheet
Set Source = ActiveWorkbook.Worksheets("Action Register")
Set Target = ActiveWorkbook.Worksheets("Sheet1")
j = 36 ' Paste to this number row
For Each cell In Source.Range("A7:A243")
If c = "Overdue" Then
Source.Range("A" & c.row & "," & "G" & c.row).Copy Target.Range("AD" & j)
Source.Range("C" & c.row & "," & "F" & c.row & "," & "H" & c.row & "," & "K" & c.row).Copy Target.Range("AF" & j)
j = j + 1
End If
Next cell
End Sub
You can pastespecial values only
For Each cell In Source.Range("A7:A243")
If cell.value = "Overdue" Then
cell.Resize(, 7).Copy
Target.Range("AD" & j).PasteSpecial xlValues
Source.Range("C" & cell.Row & "," & "F" & cell.Row & "," & "H" & cell.Row & "," & "K" & cell.Row).Copy
Target.Range("AF" & j).PasteSpecial xlValues
j = j + 1
End If
Next cell
You can also avoid the clipboard altogether and transfer the values directly, which is more efficient but it can get a bit mess you are dealing with large ranges.
Target.Range("AD" & j).Resize(,7).Value=cell.Resize(, 7).value
Related
How to combine text of multiple cells for instance translate this excel formula to VBA code
Cell F3 should =Q3&"_"&A3&"_"&D3&"_"&(ROUND(M3/1000,1))&"k"
But I would Like it to repeat in every instant so in F99= Q99&"_"&A99&"_"&D99&"_"&(ROUND(M99/1000,1))&"k"
Using VBA Code:
For Each Cel In Range("A1:A100")
If Cel.Value <> "" Then Cel.Offset(0, 5).Value = *Excel Formula NEED* "Q3&"_"&A3&"_"&D3&"_"&(ROUND(M3/1000,1))&"k""*
Saying that if value in column A insert text in same row Column E
I also think that a formula (adapted a little to return "" in case of empty cells) would be the best. But, even if you did not answer my question and you want a solution in VBA, please, test the next code:
Sub testConcatenate()
Dim sh As Worksheet, cel As Range, lastRow As Long
Set sh = ActiveSheet 'please use your sheet here
lastRow = sh.Range("A" & Rows.count).End(xlUp).Row
For Each cel In Range("A1:A" & lastRow)
If cel.value <> "" Then
cel.Offset(0, 5).value = Range("Q" & cel.Row).value & "_" & cel.value & "_" & _
Range("D" & cel.Row).value & "_" & Round(Range("M" & cel.Row).value / 1000, 1) & "k"
End If
Next
End Sub
You maybe clarify here the meaning of "" in your formula, what "k" means and what the last character "*" is used for. I did not use it...
I'm copying rows of data from one spreadsheet to another on a button press when cell I says "Yes" and deleting the original row of data. I have multiple ranges I'm copying from the same row, because the second spreadsheet doesn't need all the data held in the first. (first spreadsheet has over 20 columns worth of data but the second has half that). Is there an easy way to make sure this all gets copied to the same row in the new spreadsheet?
Basically what I'm currently doing is copying each of the ranges to the corresponding column in the new spreadsheet with the row number set to being the last used row offset by 1. Which works fine if the previous cells actually have data in, but sometimes they don't (the data is on households and some have more data than others so not all columns are always filled) so the data is placed in a different row from the rest of my data for that particular household.
Private Sub CommandButton1_Click()
Dim c As Range
Dim r As Integer
Dim LastRowD
Dim LastRowR
Dim Database As Worksheet
Dim DeReg As Worksheet
'Set worksheet deignation as needed
Set Database = ActiveWorkbook.Worksheets("Fostering Households")
Set DeReg = ActiveWorkbook.Worksheets("De-Registrations")
LastRowD = Database.Cells(Database.Rows.Count, "A").End(xlUp).Row
'Searches all rows in I
For Each c In Database.Range("I1:I" & LastRowD)
'Catches cases where "Yes" is present in column I
If c = "Yes" Then
LastRowR = Database.Cells(Database.Rows.Count, "A").End(xlUp).Offset(1, 0)
r = c.Row
'Copies the desired column data from rows containing "Yes" from Database tab and pastes it in DeReg tab
Database.Range("A" & r & ":G" & r).Copy DeReg.Range("A" & Rows.Count).End(xlUp).Offset(1, 0)
Database.Range("H" & r).Copy DeReg.Range("AJ" & Rows.Count).End(xlUp).Offset(1, 0)
Database.Range("J" & r & ":X" & r).Copy DeReg.Range("H" & Rows.Count).End(xlUp).Offset(1, 0)
Database.Range("AN" & r).Copy DeReg.Range("W" & Rows.Count).End(xlUp).Offset(1, 0)
Database.Range("AS" & r).Copy DeReg.Range("X" & Rows.Count).End(xlUp).Offset(1, 0)
Database.Range("AZ" & r & ":BH" & r).Copy DeReg.Range("Y" & Rows.Count).End(xlUp).Offset(1, 0)
End If
Next c
For i = 250 To 1 Step -1
If Database.Range("I" & i) = "Yes" Then
Database.Rows(i).EntireRow.Delete
End If
Next i
End Sub
I've tried defining the last row based on whether "A" has data in (this is the only cell that is always used) with the code:
LastRowR = Database.Cells(Database.Rows.Count, "A").End(xlUp).Offset(1, 0) and then replacing my copy past code with:
Database.Range("A" & r & ":G" & r).Copy DeReg.Range("A" & LastRowR & ":B" & LastRowR).Row
But this didn't work at all - it copied the first row it found with "Yes" in infinitely and overwrote all the data already present.
I also tried:
Database.Range("A" & r & ":G" & r).Copy DeReg.Range("A" & LastRowR).PasteSpecial
which also came with a world of problems and errors.
What I want is to search for the last used Row based on what's in column A, offset by 1, and then past the data in the column I designate, rather than the last row used being defined by the column I'm trying to paste in - is this even doable? I can't seem to find any information on this particular issue.
Also, if there is a better way of handing multiple ranges that would be great as it seems rather convoluted currently!
DeReg.Range("A" & Rows.Count).End(xlUp).Offset(1, 0) evaluates to:
DeReg.Range("A" & ActiveSheet.Rows.Count).End(xlUp).Offset(1, 0), so unless DeReg is the activesheet, you will get the wrong range.
See if this helps:
.... other code
'LastRowR = Database.Cells(Database.Rows.Count, "A").End(xlUp).Offset(1, 0)
r = c.Row
'Copies the desired column data from rows containing "Yes" from Database tab and pastes it in DeReg tab
With Database
LastRowR = DeReg.Range("A" & DeReg.Rows.Count).End(xlUp).Row + 1
.Range("A" & r & ":G" & r).Copy DeReg.Range("A" & LastRowR)
.Range("H" & r).Copy DeReg.Range("AJ" & LastRowR)
.Range("J" & r & ":X" & r).Copy DeReg.Range("H" & LastRowR)
.Range("AN" & r).Copy DeReg.Range("W" & LastRowR)
.Range("AS" & r).Copy DeReg.Range("X" & LastRowR)
.Range("AZ" & r & ":BH" & r).Copy DeReg.Range("Y" & LastRowR)
End With
End If
... other code
Some helpful tips:
i is not declared. Declare as Long.
LastRowR, r & LastRowD should be declared as Long.
Replace ActiveWorkbook with ThisWorkbook.
The copy paste method used may slow down the program, because this method copies and pastes both values and formatting.
When you want to paste in the line after last row, use +1 (Example: LastRow = sht.Cells(sht.Rows.Count, "A").End(xlUp).Row +1
Just a couple thoughts. Firstly, you have declared multiple things that are unnecessary (IMO). I have adjusted your for loop to simply loop through a value that then references the range you want. This way you can use the i value a lot more efficiently than first setting a range and then looping through and referencing the row etc.
Additionally, based on the understanding I get from your post, if you use the .UsedRanged method your outputs will start at the last row on the new sheet, irregardless of your previously chosen method by column. I have not tested the below code, but it should guide you in a clearer way.
Option Explicit
Private Sub CommandButton1_Click()
Dim i As Long
Dim LastRowD As Long
Dim LastRowR As Long
Dim Database As Worksheet
Dim DeReg As Worksheet
'Set worksheet deignation as needed
Set Database = ActiveWorkbook.Worksheets("Fostering Households")
Set DeReg = ActiveWorkbook.Worksheets("De-Registrations")
LastRowD = Database.Cells(Database.Rows.Count, "A").End(xlUp).Row
'Searches all rows in I
For i = 1 To LastRowD
'Catches cases where "Yes" is present in column I
If Database.Range("I" & i) = "Yes" Then
LastRowR = Database.UsedRange.Rows.Count + 1
'Copies the desired column data from rows containing "Yes" from Database tab and pastes it in DeReg tab
Database.Range("A" & i & ":G" & i).Copy DeReg.Range("A" & LastRowR)
Database.Range("H" & i).Copy DeReg.Range("AJ" & LastRowR)
Database.Range("J" & i & ":X" & i).Copy DeReg.Range("H" & LastRowR)
Database.Range("AN" & i).Copy DeReg.Range("W" & LastRowR)
Database.Range("AS" & i).Copy DeReg.Range("X" & LastRowR)
Database.Range("AZ" & i & ":BH" & i).Copy DeReg.Range("Y" & LastRowR)
End If
Next i
For i = 250 To 1 Step -1
If Database.Range("I" & i) = "Yes" Then
Database.Rows(i).EntireRow.Delete
End If
Next i
End Sub
I have a column (column L) in a spreadsheet in which there are many entries with some duplicate values in that column. Each "group" of duplicate values is colored in a unique color. So i have many colors in my column each of which refers to one group of duplicate values. I have to go through every "Group" so all the cells colored with the same color and do some computation. However, i don't know how to loop through all the cells that are from the same color in a column.
I would really be happy if you could help me with that :)
You could try:
Option Explicit
Sub test()
Dim LastRow As Long, i As Long, j As Long
Dim arr As Variant
With ThisWorkbook.Worksheets("Sheet1")
'Find Last row of column L
LastRow = .Cells(.Rows.Count, "L").End(xlUp).Row
'Set array starting from row 2 to LastRow of column L
arr = .Range("L2:L" & LastRow)
For i = LBound(arr) To UBound(arr)
If .Range("L" & i).Interior.Pattern <> xlNone Then
For j = LBound(arr) To UBound(arr)
If (.Range("L" & j).Interior.Pattern <> xlNone) And (i <> j) Then
If .Range("L" & i).Interior.Color = .Range("L" & j).Interior.Color Then
If .Range("N" & i).Value = "" Then
.Range("N" & i).Value = "Cell L" & i & " has the same background color with cell/s L" & j
Else
.Range("N" & i).Value = .Range("N" & i).Value & ", L" & j
End If
End If
End If
Next j
End If
Next i
End With
End Sub
Results:
Goal: Populate F and G columns with proper formulas depending on total PROD-TIME for a block
This is another issue that has come up after one of my previous questions:
How to loop through "blocks" of rows in excel dataset instead of each row individually (VBA)?
I have been able to loop through blocks of rows and can now get the sum of the PROD-TIME for that particular block. This sum is necessary to determine which formula needs to be used in the F and G columns.
This is best illustrated in this workbook,
https://www.dropbox.com/s/vgnqi00h8xosja3/wip%20Gantt%20Template.xlsx?dl=0 , where I have shown how I want the formulas to end up in the F and G columns. But for some reason when I run the macro, it just completely breaks. Some of the formulas don't even use reference cells and use the cell value instead, or reference cells don't even appear. Are the blank F and G columns confusing the macro? How can I make sure that every F and G cell gets filled with something? Errors are fine
Sub getStartEndDate()
Dim WrkSht As Excel.Worksheet
Dim RngColumn As Range, RngBlock As Range
Dim totalHrs As Integer 'total PROD-TIME for the given RngBlock
Dim lastRow As Long
lastRow = ActiveSheet.Cells.SpecialCells(xlCellTypeLastCell).Row
Set WrkSht = ActiveWorkbook.Worksheets(1)
' Populate the last row by itself first since the With-statement below needs to reference rows below current row
Range("E" & lastRow).Formula = "=ROUNDUP(D" & lastRow & "/12,0)"
Range("G" & lastRow).Value = Range("C" & lastRow).Value
Range("F" & lastRow).Formula = "=WORKDAY(G" & lastRow & ", -E" & lastRow & ")"
Columns("F:F").NumberFormat = "yyyy-mm-dd"
With WrkSht
Set RngColumn = .Range("B2:B" & lastRow)
'Starts the first block with the first cell in a column.
Set RngBlock = RngColumn.Cells(1)
'Checks every cell in a column.
For Each rngcell In RngColumn
If rngcell.Offset(0,1).Value <> "" Then
'Checks whether a cell's value equals the cell below it.
If rngcell.Value = rngcell.Offset(1, 0).Value Then
'If equal, includes the cell below in the block.
Set RngBlock = Union(RngBlock, rngcell.Offset(1, 0))
Else
'If not equal, that means the block RngBlock ends
' totalHrs is the sum of the "PROD-TIME" for that particular block
totalHrs = WorksheetFunction.Sum(Range(CStr(Trim(Chr(64 + RngBlock.Column + 2))) _
& CStr(Trim(Str(RngBlock.Row))) & ":" _
& CStr(Trim(Chr(64 + 2 + RngBlock.Column + RngBlock.Columns.Count - 1))) _
& CStr(Trim(Str(RngBlock.Row + RngBlock.Rows.Count - 1)))))
If totalHrs < 12 Then
' If total production time (PROD-TIME) is less than 12 hours, then the start and end date should be the same for all rows in that block
rngcell.Offset(0, 4).Value = rngcell.Offset(0, 1).Value
rngcell.Offset(0, 5).Value = rngcell.Offset(0, 1).Value
Else
' If total production time is greater than 12 hours, then start and end dates are based on a different formula
' e.g. Given row 11, F column formula looks like: =WORKDAY(G11, -E11), G column looks like: =IF(B11=B12,F12,C11)
rngcell.Offset(0, 4).Formula = "=WORKDAY(" & rngcell.Offset(0, 5) & ", -" & rngcell.Offset(0, 3) & ")"
rngcell.Offset(0, 5).Formula = "=IF(" & rngcell & "=" & rngcell.Offset(1, 0) & "," & rngcell.Offset(1, 4) & "," & rngcell.Offset(0, 1) & ")"
End If
'Starts the next block with the cell below.
Set RngBlock = rngcell.Offset(1, 0)
End If
End If
Next rngcell
End With
End Sub
I'm concatenating 4 different formula based columns into one using VBA (to be able to change formatting while still concatenating). The concatenating VBA code works, but when the 4 individual columns update and pull the new information, the concatenated column doesn't change.
My concatenated code is this and it lies in column D or 4:
Sub joint1()
ActiveSheet.Range("a2", ActiveSheet.Range("a2").End(xlDown)).Select
Row = 2
Col = 4
For Each Cell In Selection
AE = Cells(Row, Col + 15)
Name = Cells(Row, Col + 9)
SC = Cells(Row, Col + 16)
PM = Cells(Row, Col + 10)
Cells(Row, Col) = Name & Chr(10) & "(" & AE & " - " & SC & ")" & Chr(10) & PM & " - PM"
With Cells(Row, Col)
.ClearFormats
.Characters(1, Len(Name)).Font.Bold = True
End With
Row = Row + 1
Next
End Sub
If you know how to add a feature to help my problem, I would be very appreciative!
Try this:
Option Explicit
Sub joint1()
Dim iRow As Long
Dim iCol As Long
Dim rng As Range
Dim rngSelect As Range
Dim Name As String
Set rngSelect = ActiveSheet.Range("a2", ActiveSheet.Range("a2").End(xlDown))
iRow = 2
iCol = 4
For Each rng In rngSelect
Name = Cells(iRow, iCol + 9)
Cells(iRow, Col) = "=M" & iRow & Chr(10) & " & ""("" & S" & iRow & " & "" - "" & T" & iRow & " & "")"" &" & Chr(10) & "N" & iRow & " & ""-PM"""
With Cells(iRow, iCol)
.ClearFormats
.Characters(1, Len(Name)).Font.Bold = True
End With
iRow = iRow + 1
Next
End Sub
This code creates a formula in each cell, rather than just copying the values.
The job could probably be done just as well with an excel formula. The formatting doesn't work with my version of excel (2007).