Switch from Cells to Range - excel

I see Range.AutoFill method (Excel) example:
Set sourceRange = Worksheets("Sheet1").Range("A1:A2")
Set fillRange = Worksheets("Sheet1").Range("A1:A20")
sourceRange.AutoFill Destination:=fillRange
I want to input a formula into the first empty column (always row 2) and then copy that down for all rows in the register (it's data copied from an outside source).
Sub SetNextEmptyFormula(strFormula As Variant)
Dim ws As Worksheet
Dim lCol As Long, lRow As Long
Set ws = Workbooks("myworkbook.xlsm").Worksheets("register")
' Always row 2 -> lRow, always in lCol
lCol = ws.Range("A1").End(xlToRight).Column
lRow = ws.Range("A1").End(xlDown).Row
ws.Cells(2, lCol + i).Value = CStr(strFormula)
Set sourceRange = ws.Range(???)
Set fillRange = ws.Range(???)
sourceRange.AutoFill Destination:=fillRange
End Sub

I'm not sure how you're going to build your formula, but if you're just looking for help referencing these cells, this will do:
Option Explicit
Sub UseSub()
Dim myFormula
myFormula = "=ROW()"
Call SetNextEmptyFormula(myFormula)
End Sub
Sub SetNextEmptyFormula(strFormula As Variant)
Dim WS As Worksheet
Dim lCol As Long, lRow As Long
Dim fillRange As Range
Set WS = Workbooks("myworkbook.xlsm").Worksheets("register")
'Set WS = Workbooks("Book1.xlsm").Worksheets("register")
With WS
' Always row 2 -> lRow, always in lCol
lCol = .Range("A1").End(xlToRight).Column
lRow = .Range("A1").End(xlDown).Row
.Cells(2, lCol + 1).Formula = CStr(strFormula)
'FillDown Only requires you reference the whole range Once, You only need "FillRange"
'Set sourceRange = ws.Range(???)
Set fillRange = .Range(.Cells(2, lCol + 1), .Cells(lRow, lCol + 1))
fillRange.FillDown
End With
End Sub

Related

How to copy values from sheets to another sheet?

I'm trying to merge several sheets into one.
Configuration
DataSheet1 : First sheet
DataSheet2 : Second sheet
ConsolidatedSheet : Consolidated sheet
Code
Set consolidatedSheet = Worksheets("ConsolidatedSheet")
consolidatedSheet.Activate
startRow = 2
startCol = 1
Worksheets("DataSheet1").Activate
lastRow = Cells(Rows.Count, startCol).End(xlUp).row
lastCol = Cells(startRow, Columns.Count).End(xlToLeft).Column
Range(Cells(startRow, startCol), Cells(lastRow, lastCol)).Copy _
consolidatedSheet.Range("A" & consolidatedSheet.Cells(Rows.Count, 1).End(xlUp).row + 1)
Worksheets("DataSheet2").Activate
lastRow = Cells(Rows.Count, startCol).End(xlUp).row
lastCol = Cells(startRow, Columns.Count).End(xlToLeft).Column
Range(Cells(startRow, startCol), Cells(lastRow, lastCol)).Copy _
consolidatedSheet.Range("A" & consolidatedSheet.Cells(Rows.Count, 1).End(xlUp).row + 1)
Issue
Two arrays are created in the consolidated sheet. It means I can't sort on the consolidated sheet.
How do I copy data as values instead of arrays?
Sub consSheets()
Dim ws As Worksheet
With Worksheets("ConsolidatedSheet")
.Cells.Delete ' clear the assignment sheet first
For Each ws In Sheets(Array("DataSheet1", "DataSheet2"))
ws.Cells(2, 1).CurrentArray.Copy
.Cells(.Rows.Count, 1).End(xlUp).Offset(1).PasteSpecial Paste:=xlPasteValues
Next ws
End With
Application.CutCopyMode = False ' "clears" the clipboard
End Sub
Edit2: (not copy headers from DataSheet1 and DataSheet2 and keep existing header in ConsolidatedSheet)
Sub consSheets()
Dim ws As Worksheet
With Worksheets("ConsolidatedSheet")
.Rows("2:" & .UsedRange.Row + .UsedRange.Rows.Count).Delete ' clear (without header in Row 1) the assignment sheet first
For Each ws In Sheets(Array("DataSheet1", "DataSheet2"))
Set Rng = ws.Cells(2, 1).CurrentRegion
Set Rng = Intersect(Rng, Rng.Offset(1)) ' eliminate headers
If Not Rng Is Nothing Then
Rng.Copy
.Cells(.Rows.Count, 1).End(xlUp).Offset(1).PasteSpecial Paste:=xlPasteValues
End If
Next ws
End With
Application.CutCopyMode = False ' "clears" the clipboard
End Sub
I'm not sure what you mean by it creating arrays, and I don't think that code is actually the code using as it's not doing what you describe.
But here's something that does what your intending.
Option Explicit
Sub Test()
Dim cSht As Worksheet
Set cSht = Worksheets("ConsolidatedSheet")
Dim StartRow As Integer, StartCol As Integer
StartRow = 1
StartCol = 1
'Split out to a sub and don't need to repeat self
Call ConsolidateData(cSht, "DataSheet1", StartRow, StartCol, True)
Call ConsolidateData(cSht, "DataSheet2", StartRow, StartCol)
End Sub
Private Sub ConsolidateData(cSht As Worksheet, FromSheet As String, StartRow As Integer, StartCol As Integer, Optional IncludeHeader As Boolean)
Dim FromRow As Integer
If IncludeHeader Then
FromRow = StartRow
Else
FromRow = StartRow + 1
End If
With Worksheets(FromSheet)
lastrow = .Cells(.Rows.Count, StartCol).End(xlUp).Row
lastcol = .Cells(StartRow, .Columns.Count).End(xlToLeft).Column
'Just transfering value is faster then copy, but doesn't bring formatting
cSht.Cells(cSht.Rows.Count, 1).End(xlUp).Resize(lastrow - FromRow, lastcol - StartCol).Value2 = .Range(.Cells(FromRow, StartCol), .Cells(lastrow, lastcol)).Value2
End With
End Sub

VBA Loop : Copy / Paste destination offsetting

First of all thanks for your help. I need to copy / paste datas. The idea is the next : depending on the cells content from the sheet AAA I want to copy / paste the datas to the corresponding sheet (XXX if XXX or to ZZZ if ZZZ).My macro worked but the issue is that I have an offset bothering me. Imagine , the first lap will paste the data to XXX , but the second lap will copy to ZZZ , in this case I have an issue because it will copy paste to the 3rd cells (3,1) whereas the cell(2,1) is empty
Sub CopyPastingMyDate()
Dim i As Long
Dim lrow As Long
Dim lcol As Long
Dim RngOne As Range
Dim RngTwo As Range
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("AAA")
lrow = ws.Cells(Rows.Count, 1).End(xlUp).Row
lcol = ws.Cells(1, Columns.Count).End(xlToLeft).Column
Set RngOne = ws.Range(ws.Cells(lrow, 1), ws.Cells(1, lcol))
For i = 2 To lrow
Set RngOne = ws.Range(ws.Cells(lrow, 1), ws.Cells(1, lcol))
If ws.Cells(i, 1) = "XXX" Then
Set RngTwo = ThisWorkbook.Worksheets("SheetXXX").Range(ThisWorkbook.Worksheets("SheetXXX").Cells(i, 1), ThisWorkbook.Worksheets("SheetXXX").Cells(i, lcol))
RngOne.Copy
RngTwo.PasteSpecial xlAll
End If
If ws.Cells(i, 1) = "ZZZ" Then
Set RngTwo = ThisWorkbook.Worksheets("SheetZZZ").Range(ThisWorkbook.Worksheets("SheetZZZ").Cells(i, 1), ThisWorkbook.Worksheets("SheetZZZ").Cells(i, lcol))
RngOne.Copy
RngTwo.PasteSpecial xlAll
End If
Next i
End Sub
How to fix it please ? I want to copy paste to from the first available cell. Thanks to all of you.
JaNa
Try this. I might be misunderstanding what you're copying though: I'm assuming each row needs to be copied to the correct sheet?
Sub CopyPastingMyDate()
Dim i As Long
Dim lrow As Long
Dim lcol As Long
Dim RngOne As Range
Dim RngTwo As Range
Dim ws As Worksheet, dest, wsDest As Worksheet
Set ws = ThisWorkbook.Worksheets("AAA")
lrow = ws.Cells(Rows.Count, 1).End(xlUp).Row
lcol = ws.Cells(1, Columns.Count).End(xlToLeft).Column
Set RngOne = ws.Range(ws.Cells(lrow, 1), ws.Cells(1, lcol))
For i = 2 To lrow
Select Case ws.Cells(i, 1).Value 'which destination sheet?
Case "XXX": dest = "SheetXXX"
Case "ZZZ": dest = "SheetZZZ"
Case Else: dest = ""
End Select
If Len(dest) > 0 Then
ws.Cells(i, 1).Resize(1, lcol).Copy 'copy the row
Set wsDest = ThisWorkbook.Worksheets(dest)
wsDest.Cells(wsDest.Rows.Count, 1).End(xlUp).Offset(1, 0).PasteSpecial xlAll
End If
Next i
End Sub
I have found a way to solve my issue by introducing a new variable x = last_row + 1 . I replaced in i in RngTwo by x .

select entire row with flexibility

I am looking for a way to select an entire row but skip the first 3 columns of the same row without using 'range()' command. What command can i use?
You can use a combination of Cells and Resize:
Range.Cells Property
Range.Resize Property
Depending on how you ask the question (skip first column or first column is), you can use the combination as follows:
Option Explicit
Sub EntireSkipColumns()
Dim ws As Worksheet: Set ws = ActiveSheet
Dim rng As Range
Dim FR As Long: FR = 2
Dim LR As Long: LR = 10
Dim i As Long
Dim j As Long: j = 3 ' Skip first 3 columns
For i = FR To LR
Set rng = ws.Cells(i, j + 1).Resize(, ws.Columns.Count - j)
With rng
' To check if the range is correct.
Debug.Print .Address(False, False)
' Cycle Interior ColorIndex
'.Interior.ColorIndex = i
End With
Next i
End Sub
Sub EntireFirstColumn()
Dim ws As Worksheet: Set ws = ActiveSheet
Dim rng As Range
Dim FR As Long: FR = 2
Dim LR As Long: LR = 10
Dim i As Long
Dim j As Long: j = 4 ' Use 4 as the first column
For i = FR To LR
Set rng = ws.Cells(i, j).Resize(, ws.Columns.Count - j + 1)
With rng
' To check if the range is correct.
Debug.Print .Address(False, False)
' Cycle Interior ColorIndex
'.Interior.ColorIndex = i
End With
Next i
End Sub
EDIT:
Set rngTarget = rngTarget.Offset(1) is only used to move each result a row below.
Sub QualifyCellsToo()
Dim wsSource As Worksheet: Set wsSource = ThisWorkbook.Worksheets("Sheet1")
Dim wsTarget As Worksheet: Set wsTarget = ThisWorkbook.Worksheets("Sheet2")
Dim rngSource As Range
Dim rngTarget As Range
' This is wrong:
'Worksheets("sheets1").Range(Cells(3, 4), Cells(3, 9)).Copy _
Worksheets("sheets2").Range(Cells(3, 4), Cells(3, 9))
' You have to qualify 'Cells', too:
Worksheets("Sheet1").Range(Worksheets("Sheet1").Cells(3, 4), _
Worksheets("Sheet1").Cells(3, 9)).Copy _
Worksheets("Sheet2").Range(Worksheets("Sheet2").Cells(3, 4), _
Worksheets("Sheet2").Cells(3, 9))
' This is a long expression, so using variables is preferred.
Set rngSource = wsSource.Range(wsSource.Cells(3, 4), wsSource.Cells(3, 9))
Set rngTarget = wsTarget.Range(wsTarget.Cells(3, 4), wsTarget.Cells(3, 9))
Set rngTarget = rngTarget.Offset(1)
rngTarget.Resize(10).Clear
' Copy values or formulas and formats using same sized ranges.
rngSource.Copy rngTarget
Set rngTarget = rngTarget.Offset(1)
' Copy values or formulas and formats using only the first cell
' of Target Range.
rngSource.Copy rngTarget.Cells(1)
Set rngTarget = rngTarget.Offset(1)
' Copy values
rngTarget.Value = rngSource.Value
Set rngTarget = rngTarget.Offset(1)
' Copy values using target without '.Value'
rngTarget = rngSource.Value
Set rngTarget = rngTarget.Offset(1)
End Sub

Bloomberg data not populating before vba has finished running

I know similar questions have been asked in the past, but looking through those posts, I haven't been able to find a solution to the following issue.
I have 2 subs that use Bloomberg API formulas. In the second (Setup_2) the variable LastRow1 is dependent on Setup_1 having populated to work properly.
Using checkStatus_1 and checkStatus_2 I can run each of the 2 setup subs independently, but when I try to create a separate sub calling them, it doesn't work, as the data that LastRow1 depends on isn't there.
Here is the relevant code:
Sub Setup_1()
Dim ws1 As Worksheet
Set ws1 = Worksheets("Returns")
ws1.Cells(2, 1).Formula = "=BDS(Control!B4,""INDX_MWEIGHT_HIST"",""END_DATE_OVERRIDE"",TEXT($A$1,""YYYYMMDD""))"
ws1.Cells(1, 4).Formula = "=BDH(A2&"" Equity"",""DAY_TO_DAY_TOT_RETURN_GROSS_DVDS"",$B$1,$A$1,""dir=h"")"
ws1.Cells(3, 4).Formula = "=BDH(A3&"" Equity"",""DAY_TO_DAY_TOT_RETURN_GROSS_DVDS"",$B$1,$A$1,""dir=h"",""dts=h"")"
checkStatus_1
End Sub
Sub Setup_2()
Dim ws1 As Worksheet
Set ws1 = Worksheets("Returns")
Dim LastRow1 As Long
LastRow1 = ws1.Cells(Rows.Count, 1).End(xlUp).Row
ws1.Cells(3, 4).Formula = "=BDH(A3&"" Equity"",""DAY_TO_DAY_TOT_RETURN_GROSS_DVDS"",$B$1,$A$1,""dir=h"",""dts=h"")"
ws1.Cells(3, 4).AutoFill Destination:=ws1.Range(ws1.Cells(3, 4), ws1.Cells(LastRow1, 4))
checkStatus_2
End Sub
Sub Setup_3()
Dim ws1 As Worksheet
Set ws1 = Worksheets("Returns")
Dim LastRow1 As Long
Dim LastCol1 As Long
Dim LCol As String
LastRow1 = ws1.Cells(Rows.Count, 1).End(xlUp).Row
LastCol1 = ws1.Cells(1, Columns.Count).End(xlToLeft).Column
LCol = Split(Cells(, LastCol1).Address, "$")(1)
ws1.Cells(2, 3).Formula = "=(STDEV.S(D2:" & LCol & "2)*SQRT(252))/100"
ws1.Cells(2, 3).AutoFill Destination:=ws1.Range(ws1.Cells(2, 3), ws1.Cells(LastRow1, 3))
End Sub
Sub checkStatus_1()
Dim ws1 As Worksheet
Dim rng As Range
Dim c As Range
Set ws1 = Worksheets("Returns")
Set rng = Application.Union(ws1.Cells(2, 1), ws1.Cells(1, 4), ws1.Cells(3, 4))
For Each c In rng
If "#N/A Requesting Data..." = c Or "#N/A Invalid Securiity" = c Then
Application.OnTime (Now + TimeValue("00:00:02")), "checkStatus_1"
Exit Sub
End If
Next c
End Sub
Sub checkStatus_2()
Dim ws1 As Worksheet
Dim rng As Range
Dim c As Range
Dim LastRow1 As Long
Set ws1 = Worksheets("Returns")
LastRow1 = ws1.Cells(Rows.Count, 1).End(xlUp).Row
Set rng = ws1.Range(ws1.Cells(3, 4), ws1.Cells(LastRow1, 4))
For Each c In rng
If "#N/A Requesting Data..." = c Then
Application.OnTime (Now + TimeValue("00:00:02")), "checkStatus_2"
Exit Sub
End If
Next c
End Sub

VBA- Transferring data to another work sheet if a column has certain text and pasting it in a certain cell range

I am currently trying to filter data and paste it into another sheet to a certain range but it is only posting the latest data row. How do I fix the code so that it selects all the rows with the code word and pastes it into the other sheet.
This is my code:
Private Sub CommandButton1_Click()
Dim lastrow As Long, i As Long
lastrow = Sheets("Sheet1").Range("A" & Rows.Count).End(xlUp).Row
For i = 2 To lastrow
If Sheets("sheet1").Cells(i, 1) = "pp" Then
Sheets("sheet1").Range(Cells(i, 2), Cells(i, 5)).Copy
ActiveSheet.Paste Destination:=Worksheets("Sheet5").Range("A11:A22")
End If
Next
End Sub
I think this is what you want.
Private Sub CommandButton1_Click()
Dim ws1 as Worksheet: Set ws1 = Thisworkbook.Sheets("Sheet1")
Dim ws2 as Worksheet: Set ws2 = Thisworkbook.Sheets("Sheet5")
Dim LRow1 As Long, LRow2 as Long, i As Long
LRow1 = ws1.Range("A" & ws1.Rows.Count).End(xlUp).Row
LRow2 = ws2.Range("A" & ws2.Rows.Count).End(xlUp).Row
For i = 2 To lastrow
If ws1.Cells(i, 1) = "pp" Then
ws1.Range(Cells(i, 1), Cells(i, 5)).Copy
ws2.Range("A" & LRow + 1).PasteSpecial xlPasteValues
End If
Next
End Sub
Here is a more effecient method using a For Each loop and one instance of Copy/Paste instead of 1 iteration for every matched cell.
Option Explicit
Sub Copy()
Dim ws1 As Worksheet: Set ws1 = ThisWorkbook.Sheets("Sheet1")
Dim ws2 As Worksheet: Set ws2 = ThisWorkbook.Sheets("Sheet2")
Dim TargetRange As Range, TargetCell As Range, CopyRange As Range
Set TargetRange = ws1.Range("A2:A" & ws.Range("A" & ws.Rows.Count).End(xlUp).Row)
For Each TargetCell In TargetRange
If TargetCell = "pp" Then
If CopyRange Is Nothing Then
Set CopyRange = TargetCell.Resize(1, 4)
Else
Set CopyRange = Union(CopyRange, TargetCell.Resize(1, 4))
End If
End If
Next TargetCell
CopyRange.Copy
ws2.Range("A" & ws2.Range("A" & ws2.Rows.Count).End(xlUp).Row).PasteSpecial xlPasteValuesAndNumberFormats
End Sub
Another method would be to apply a filter for your target value pp and then copy/paste visible cells.

Resources