I have a weekly report that I am running. I have two separate worksheets. In the first worksheet I input my data (a table with 2 columns and unknown number of rows beforehand) and I want to create a macro where I click it and I cut all these data, and move them to the other worksheet. In the worksheet where the table is pasted, I want the data to be pasted as values ( include the initial formulas) and be pasted below the data from the previous week.
e.g. If I cut data from Worksheet1 from cells A1:B7, I want to paste the values in Worksheet2, in cells A7:B14. Next week, the data should be cut-pasted from cells A1:B5 in Worksheet1 to cells A15:B20 in Worksheet2
I have this code so far but I am doing something wrong. I am at a beginner level with vba.
Sub Movetabletototal()
Dim Count As Integer
Dim Table As Range
Dim CountRange As Range
Worksheets("TOTAL").Select
Set CountRange = Range("A2:A1000")
Count = Application.WorksheetFunction.Count(CountRange)
Worksheets("MIXER TOTAL").Select
Set Table = Range("P3:Q12")
Worksheets("TOTAL").Select
Worksheets("TOTAL").Range("A1").Select
ActiveCell.Offset(1, Count + 1).Select
ActiveCell.Value = Table
Worksheets("MIXER TOTAL").Select
Worksheets("MIXER TOTAL").Range("P3:Q12").Clear Contents
If Worksheets("TOTAL").Range("A2").Offset(1, Count) <> "" Then
Worksheets("TOTAL").Range("A2").End(xlDown).Select
End If
End Sub
Thank you!
This code successfully does this:
e.g. If I cut data from Worksheet1 from cells A1:B7, I want to paste
the values in Worksheet2, in cells A7:B14. Next week, the data should
be cut-pasted from cells A1:B5 in Worksheet1 to cells A15:B20 in
Worksheet2
Edit per your comment:
Using P3:Q12 on "MIXER TOTAL" as your data that changes, and pasting to columns A:B on the "TOTAL" sheet after current data.
Sub Movetabletototal()
Dim Count As Integer
Dim copyRng As Range, pasteRng As Range
Dim totalWS As Worksheet, mixerWS As Worksheet
Set totalWS = Worksheets("TOTAL")
Set mixerWS = Worksheets("MIXER TOTAL")
Set copyRng = mixerWS.Range("P3:Q" & mixerWS.Cells(mixerWS.Rows.Count, 17).End(xlUp).Row)
Dim newRow As Long
newRow = totalWS.Cells(totalWS.Rows.Count, 1).End(xlUp).Row
If newRow > 1 Then newRow = newRow + 1
copyRng.Copy totalWS.Range(totalWS.Cells(newRow, 1), totalWS.Cells(newRow + copyRng.Rows.Count, copyRng.Columns.Count))
copyRng.ClearContents
End Sub
Change those ranges as necessary. (Note, currently if your data goes from P3:Q1000, it'll copy all that range. If you strictly want P3:Q12, then change CopyRng to just mixerWS.Range("P3:Q12")
Related
so recently I have been looking into using defined ranges to copy data instead of selecting, copying and pasting cells. This way I hope to optimise the performance and the runtime of my code.
Unfortunately I have come to face a problem I wasn't able to solve on my own.
When defining a range I want to rearrange the columns in a different order.
For example:
Set my_range = Sheets("Sheet1").Range("A2:E2,G2:H2,J2:K2,M2")
Works well, as the columns I fill into the range are behind each other in the sheet. But now I have this:
Set yo_range = Sheets("Sheet2").Range("D2,AV2,L2,H2,Q2,AE2,AG2")
If I fill these ranges into a new sheet the yo_range will fill the columns I put into it but not in the order I written down. It will put it down in the order according to the original one. In this example yo_range would put the data in this order into the new sheet:
D2 | H2 | L2 | Q2 | AE2 | AG2 | AV2
How can I fix this? I want the order to be another one than the original one.
Also - as you can see my_range has more columns than yo_range. How can I let yo_range be filled into the new sheet but at certain points leave columns out? For example:
my_range(A2:E2) goes into A2:E2 in the new sheet
yo_range(D2,AV2) goes into A:B in the new sheet, then leave C out and then paste yo_range(L2,H2) into D:E in the new sheet
I hope that I was able to explain my problem well and that there is somebody able and willing to help me. Any help is appreciated.
Edit:
Here's the code that puts the values from the ranges into the new sheet
Do
If Application.WorksheetFunction.CountA(my_range) > 0 Then
my_range.Copy ws.Range("A" & ws.Rows.Count).End(xlUp).Offset(1, 0)
Set my_range = my_range.Offset(1, 0)
Else
Exit Do
End If
Loop
Do
If Application.WorksheetFunction.CountA(yo_range) > 0 Then
yo_range.Copy ws.Range("A" & ws.Rows.Count).End(xlUp).Offset(1, 0)
Set yo_range = yo_range.Offset(1, 0)
Else
Exit Do
End If
Loop
We can see that the Copy method will re-arrange the data left-to-right. Try this:
Option Explicit
Public Sub CheckClipboard()
Dim ws As Worksheet
Dim rngToCopy As Range
Dim objData As Object
Dim varContents As Variant
' test data b,c,d,e,f,g in Sheet1!B1:G1
Set ws = ThisWorkbook.Worksheets("Sheet1")
ws.Range("B1:G1").Value = Array("b", "c", "d", "e", "f", "g")
Set rngToCopy = ws.Range("E1:F1,G1,B1:C1") '<-- note not left-to-right order
rngToCopy.Copy '<-- copy
' this is a late bound MSForms.DataObject
Set objData = CreateObject("New:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
' copy current cell formula to clipboard
objData.GetFromClipboard
varContents = objData.GetText
Debug.Print varContents '<-- re-arranged left-to-right
' cancel copy
Application.CutCopyMode = False
End Sub
I get this in the immediate window:
b c d e f g
So, using Copy is not going to work for what you want to do.
In order to 'paste' the data in the order that you set it in the Range, you need to iterate each Area of the Range and then each cell (i.e. Range) in each Area. See the test code below which replicates your issue and presents a solution:
Option Explicit
Sub MixColumns()
Dim ws As Worksheet
Dim rngIn As Range
Dim rngOut As Range
Dim lng As Long
Dim rngArea As Range
Dim rngCell As Range
Set ws = ThisWorkbook.Worksheets("Sheet1")
' example 1
Set rngIn = ws.Range("B1:C1,E1:F1,G1") '<-- 5 cells, non-contiguous, forward order
Set rngOut = ws.Range("B2:F2") '<-- 5 contiguous cells
rngIn.Copy rngOut '<-- works
' example 2 - OP problem
Set rngIn = ws.Range("E1:F1,G1,B1:C1") '<-- 5 cells, non-contiguous, odd order
Set rngOut = ws.Range("B3:F3") '<-- 5 contiguous cells
rngIn.Copy rngOut '<-- should be e,f,g,b,c but gets b,c,e,f,g
' example 3 - solution for OP problem
Set rngIn = ws.Range("E1:F1,G1,B1:C1") '<-- 5 cells, non-contiguous, odd order
Set rngOut = ws.Range("B4:F4") '<-- 5 contiguous cells
lng = 1 '<-- rngOut cell counter
' iterate areas
For Each rngArea In rngIn.Areas
' iterate cells in area
For Each rngCell In rngArea.Cells
rngOut.Cells(1, lng).Value = rngCell.Value '<-- copy single value
lng = lng + 1 '<-- increment rngOut counter
Next rngCell
Next rngArea '<-- results in e,f,g,b,c
End Sub
Give this output:
I have a 3 column table in excel named "RFQ_selector". The 2nd column contains yes/no.
I need a macro that will filter the table for only rows that contain 'Yes' in the 2nd column.
Then the macro should copy every cell to the left of a row which contains a yes into a new location on the same sheet. Pasting them in a list starting at cell F25
I'm getting stuck, can someone help please.
Thanks
Sub CopyYes()
Dim c As Range
Dim j As Integer
Dim Source As Worksheet
Dim Target As Worksheet
' Change worksheet designations as needed
Set Source = ActiveWorkbook.Worksheets("Trader")
Set Target = ActiveWorkbook.Worksheets("Sheet2")
j = 1 ' Start copying to row 1 in target sheet
For Each c In Source.Range("C8:C22") ' Do 30 rows
If c = "yes" Then
Source.Rows(c.Row).Copy Target.Rows(j)
j = j + 1
End If
Next c
End Sub
I've modified your sub to reflect your desired changes:
Copy every cell to the left of a row which contains a yes into a new location on the same sheet. Pasting them in a list starting
at cell F25
It does not filter, there was no filtering happening in your provided code but the output only includes information for the "Yes" columns
Sub CopyYes()
Dim c As Range
Dim j As Integer
Dim Source As Worksheet
'Target worksheet not needed, pasting to source worksheet
' Change worksheet designations as needed
Set Source = ActiveWorkbook.Worksheets("Sheet1")
j = 25 'Start copying to F25
For Each c In Source.Range("B2:B30") 'Change the range here to fit the range in which your data for Yes/No is stored
If c = "Yes" Then 'Verify capitalization here, difference between "Yes" and "yes"
c.Offset(0, -1).Copy Source.Range("F" & j) 'Copy the cell to the left of the Yes/No column and paste on same sheet starting at row F25
j = j + 1
End If
Next c
End Sub
I am trying to take two sheets in a workbook and highlight cells in Sheet2 that are different from Sheet1. The sheets can range from a small number of rows to hundreds of them. I will be happy to answer any questions, I have never used VBA before, but I have experience in other languages.
It needs to go by Sheet2's rows, then cells within the current row. Take the first cell in the row and see if the contents of that cell exists within Sheet1, if that cell's contents don't exist, highlight the whole row as a new entry. If the contents do appear in Sheet1, go through each cell of the row that entry appears on in each sheet and highlight changes on only Sheet2.
All I have figured out so far:
Sub DetectChanges()
Rem compares two sheets by row. let sheet1 be the old one and sheet2 be the new one.
Rem *hopefully* highlights any differences. Make column1 unique identifiers
Dim ws1, ws2 As Worksheet
Set ws1 = Worksheets("Sheet1")
Set ws2 = Worksheets("Sheet2")
For Each rw In ws2.Rows
' check identifier for active row & detect changes
Next
End Sub
Thank you for any help!
edited after OP's clarifications
this (commented) code should get you on the right way:
Option Explicit
Sub DetectChanges()
Dim ws1 As Worksheet, ws2 As Worksheet '<-- explicitly declare each variable type
Dim ws1Data As Range, f As Range, cell As Range
Dim icol As Long
Set ws1Data = Worksheets("Sheet01").Columns(1).SpecialCells(xlCellTypeConstants) '<-- set a range with Sheet1 cells containing data
With Worksheets("Sheet02") '<--| reference Sheet2
For Each cell In Intersect(.UsedRange, .Columns(1)).SpecialCells(xlCellTypeConstants) '<-_| loop through its column "A" non blank cells
Set f = ws1Data.Find(what:=cell.value, LookIn:=xlValues, LookAt:=xlWhole) '<--| search for current cell value in Sheet1 data
If f Is Nothing Then '<--| if not found then...
Intersect(cell.EntireRow, .UsedRange).Interior.ColorIndex = 3 '<--| highlight current cell entire row
Else
For icol = 1 To .Range(cell, .Cells(cell.Row, .Columns.Count).End(xlToLeft)).Columns.Count - 1 '<--| loop through Sheet2 current cell row
If f.Offset(, icol) <> cell.Offset(, icol) Then '<--| if it doesn't match corresponding cell in Sheet1
cell.Offset(, icol).Interior.ColorIndex = 3 '<--| highlight Sheet2 not-matching cell
f.Offset(, icol).Interior.ColorIndex = 3 '<--| highlight Sheet1 not-matching cell
End If
Next icol
End If
Next cell
End With
End Sub
What I am trying to do is, in each worksheet:
1. Copy all numbers in column G (G23 and down) and paste special at the end of column A.
2. Format the pasted numbers to have only one decimal point.
3. Copy the pasted numbers and paste them at the end of column B, and remove duplicates.
I finished Step 1, but I don't know how to do Step 2 and 3.... I could not find ways to select the just pasted numbers at the bottom of Column A. I am new to VBA - Many thanks for your help.
Here is the code I have so far:
Sub WorksheetLoop()
Dim WS_Count As Integer
Dim I As Integer
Dim rng As Range
Dim last As Long
'Set WS_Count equal to the number of worksheets in the active workbook.
WS_Count = ActiveWorkbook.Worksheets.Count
'Begin loop, starts from the sixth worksheet
For I = 6 To WS_Count
last = Worksheets(I).Cells(Rows.Count, "G").End(xlUp).Row
Set rng = Worksheets(I).Range("G23:G" & last)
Worksheets(I).Select
rng.Copy
Worksheets(I).Cells(Rows.Count, 1).End(xlUp)(2).PasteSpecial xlPasteFormulasAndNumberFormats
....(what should I do next here?)
Next I
Application.ScreenUpdating = True
End Sub
You already know the range of the values to be pasted. The first cell of that range is the one used for PasteSpecial and the number of rows will be equal to the number of rows in rng. The required information is already there, all that is needed is to set it to a variable.
Here's a snippet to illustrate:
Sub Example()
Dim last As Long
Dim copyRange As Range
Dim pasteRange As Range
last = Worksheets(1).Cells(Rows.Count, "G").End(xlUp).Row
Set copyRange = Worksheets(1).Range("G23:G" & last)
Set pasteRange = Worksheets(1).Cells(Rows.Count, 1).End(xlUp)(2) _
.Resize(copyRange.Cells.Count, 1)
copyRange.Copy
pasteRange.PasteSpecial xlPasteFormulasAndNumberFormats
' use pasteRange for modifying the pasted data
End Sub
Changing the format can be done with range.NumberFormat. In this case you could do:
pasteRange.NumberFormat = "0.0"
I find it rather strange that you first copy the NumberFormat and then change it, though! Maybe you could choose to format the entire column A and not paste the formatting?
range.RemoveDuplicates is built in Excel for the third step. Here are a couple of answers that showcase how it can be used:
Remove Duplicates from range of cells in excel vba
Delete all duplicate rows Excel vba
I've seen a lot of people talking about this problem but more from a point of view of copying merged cells into single cells. I have a procedure that gets a range from a workbook, opens the second workbook and attempts to paste it into the next blank cell in the specified row;
Public Sub BankBalances()
Dim fname As String
Dim fname2 As String
Dim mt As String, yr As String
'get the selected month
mt = MonthBox.Value
'get the selected year
yr = YearBox.Value
'set the file path to the selected year, month and the saving format
fname = yr & mt & "DB" & ".xlsx"
'set the file path to the selected year, month to open the trial balance sheet
fname2 = yr & mt & "TB" & ".xlsx"
'get the ranges
Dim rng1 As Range
Dim rng2 As Range
Set rng1 = Workbooks(fname2).Worksheets("excel").Range("I100")
'check for the next empty cell in row 55
Set rng2 = Workbooks(fname).Worksheets("UK monthly dashboard").Cells(55, Columns.Count).End(xlToLeft).Offset(0, 1)
'set the new range to hold the data from the original range
rng2.Value = rng1.Value
'set the result to format according to the other information in the workbook
rng2.Value = Round(rng1.Value / 1000, 0)
End Sub
The above code will paste the data in the next blank cell in the row that is not merged. I need it to be able to paste into the merged cells.
What I want to know is if there is a way using VBA to put the data into the merged cell or if I will need to do a separate procedure to check for merged cells, unmerge them and then merge them once the data has copied across.
If that is the way, would I be able to do that in a similar way to checking for the next empty cell, then check if it's merged, then carry out the unmerge and merge again.
If I understand what you are saying then yes, but if I may alter your example I want the contents of say A1 put into D1:D2 that are merged. So its a value of one cell going into two merged together – JamesDev 4 hours ago
Is this what you are trying?
Sub Sample()
Dim Rng1 As Range
Dim Rng2 As Range
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Sheet1")
With ws
Set Rng1 = .Range("A1")
Set Rng2 = .Range("D1:D2")
'~~> Check if cells are merged
If Rng2.MergeCells Then
'~~> If merged then write to first cell
Rng2.Cells(1, 1).Value = Rng1.Value
Else
Rng2.Value = Rng1.Value
End If
End With
End Sub