For Loop Copy and Paste Excel VBA - excel

Function Iterate()
Dim i As Integer
For i = 1 To 10
Worksheets("Calculator").Calculate
Worksheets("Calculator").Range("AC6:AC16").Copy Destination:=Sheets("Iterations").Range("A1:A10")
Worksheets("Calculator").Range("AT10:AT11").Copy Destination:=Sheets("Iterationas").Range("A11:A12")
Worksheets("Iterations").Paste
Next
End Function
My Goal, is to run this loop as many times as I'll need, and after every single loop, I want excel to take the Range("cells") and copy them to the "Iterations" worksheet.
The data on Calculator is refreshed every loop, so new calculations appear. Once the new calculations appear, I want to paste it one next to the other (which I don't know how to do).
For now, this gives me a runtime error Subscript it out of range
Any advice?

I have tried the following:
Option Explicit
Public Sub Iterate()
Dim i As Long
For i = 1 To 10
Worksheets(1).Calculate
Worksheets(1).Range("AC6:AC16").Copy Destination:=Worksheets(2).Range("A1:A10")
Worksheets(1).Range("AT10:AT11").Copy Destination:=Worksheets(2).Range("A11:A12")
Next
End Sub
It works, just make sure that you rename the Worksheets(1) and (2) relevantly. In general, use Function, when you expect a value to be returned. For changes in a worksheet, use Sub.
In general, what you wanted in the comments is to copy the values and to put them next to each other column. Here is how to get it:
Option Explicit
Public Sub Iterate()
Dim i As Long
For i = 1 To 10
With Worksheets(1)
Worksheets(2).Calculate
Worksheets(2).Range("AC6:AC16").Copy
.Cells(1, i).PasteSpecial Paste:=xlPasteValues
Worksheets(2).Range("AT10:AT11").Copy
.Cells(1, i + 10).PasteSpecial Paste:=xlPasteValues
Application.CutCopyMode = False
End With
Next
End Sub

Related

Is there a VBA code to select multiple (and varied totals of) columns from multiple worksheets to copy and paste into a new worksheet

I am trying to copy multiple columns from multiple worksheets into a new worksheet in Excel using a VBA Macro.
I have already created the worksheet, and I want to paste specific columns one after another in that worksheet.
I would like to copy from each worksheet all columns including and beyond a certain column, in all worksheets including and from Column F.
I have written a piece of code that selects the appropriate data and loops correctly.
However, i get a "run-time error 1004", when the loop hits a worksheet where I am copying only one column.
I know this is because of the choice of my code. However, I don't know how to solve the problem.
The problem is that my code selects a range to the end of the worksheet when there is only one column being selected. This creates a copied area too big to paste in the new worksheet.
Dim i As Integer
i = 1
Do While i <= Worksheets.Count - 1
Worksheets(i).Select
'Select, Copy and Paste Data
RangeFromF1
Selection.Copy
Worksheets("Combined").Select
Range("X1").Select
Selection.End(xlToLeft).Select
ActiveCell.Offset(0, 1).Select
ActiveSheet.Paste
i = i + 1
Loop
End Sub
Public Sub RangeFromF1()
Range("F1", Range("F1").End(xlDown).End(xlToRight)).Select
End Sub
Instead of going from column F to the right, try going from the last column to the left.
Public Sub RangeFromF1()
Range("F1", Cells(1, Columns.Count).End(xlToLeft).End(xlDown)).Select
End Sub
You might also want to get rid of all the Select stuff.
Sub CopyStuff()
Dim i As Long
i = 1
Do While i <= Worksheets.Count - 1
With Worksheets(i)
.Range("F1", .Cells(1, .Columns.Count).End(xlToLeft).End(xlDown)).Copy
Worksheets("Combined").Cells(1, Columns.Count).End(xlToLeft).Offset(, 1).Paste
i = i + 1
End With
Loop
End Sub
Before coming back to check for your answer noris, I figured out a way, to do as you suggested, with the following code:
Public Sub ReferenceSelection()
Dim startcell As Range
Set startcell = Range("A1").End(xlDown).End(xlToRight)
Range(startcell, ("F1")).Select
End Sub

Select row for each worksheet with activecell

I need a small loop that cuts a row and inserts it at the row 2 for every worksheet.
The entire row should be detected or selected by only selecting a single cell in the first column.
I've tried adding a simple for each to the code (see below) but it end up sorting the every row by date.
Private Sub CommandButton2_Click()
For Each Worksheet In ThisWorkbook
Rows(ActiveCell.Row).Cut
Rows(2).Insert Shift:=xlDown
Next
End Sub
It should move the entire row, in every worksheet, to the top of the list by only selecting a cell and pressing the commandbutton in the first worksheet.
The entire row should be detected or selected by only selecting a single cell in the first column.
If someone could also explain how to work with Activevell and a loop through every worksheet that would be nice as well.
Well the bare minimum of code you are trying to use would look like:
Private Sub CommandButton2_Click()
For Each ws In ThisWorkbook.Sheets
ws.Rows(ActiveCell.Row).Cut
ws.Rows(2).Insert Shift:=xlDown
Next ws
End Sub
This would loop through all elements (sheets) in the sheets collection of the current workbook. Activecell is a reference to the focussed cell currently displayed on the active sheet, the sheet as where you press the commandbutton (assumed) as per your statement:
"It should move the entire row, in every worksheet, to the top of the list by only selecting a cell and pressing the commandbutton in the first worksheet."
I am not a big fan of For Each loop, that's why I'm using just for next loop :)
I think it should be useful :)
Private Sub CommandButton2_Click()
Dim numb As Integer
Dim i As Integer
Dim pos As Integer
numb = Application.Worksheets.Count
For i = 1 To numb
With Sheets(i)
.Select
pos = ActiveCell.Row
.Rows(pos).Cut
.Rows(2).Insert shift:=xlDown
End With
Next i
End Sub
If You still need answer for your last sentence add a comment, hope it helps :)

How can I do a Calculation in Microsoft Excel VBA?

I'm 15 and I'm doing a Internship as a Developer and I've got a kinda hard exercise.
I have a Table with 3 columns, A is "Number" B is "percent" and C is "Value". The column "value" is blank and I Need to calculate the value with a macro button. I've tried this, but it was wrong because I didnĀ“t calculate it in VBA:
Public Sub PushButton ()
Range("C2:C11").Formula = "=A2*B2/100"
Range("C2:C11").Value = Range("C1:C6).Value
End Sub
How do I solve this?
You are using a defined range, you could do it with a dynamic range like this:
Option Explicit
Sub PushButton()
Dim i As Long, LastRow As Long
With ThisWorkbook.ActiveSheet
LastRow = .Cells(.Rows.Count, 1).End(xlUp).Row 'first you need to find the last row on the active sheet
For i = 2 To LastRow 'then iterate through all the rows starting from 2, if row 1 has headers
.Cells(i, 3) = .Cells(i, 1) * .Cells(i, 2) / 100
Next i
End With
End Sub
If you need help understanding this code, let me know.
Edit: Explanation
Well, the first thing you must do is Dimension all your variables, and to help that you can use the Option Explicitright above all your code.
I've dimensioned 1 variable for the loop and another one to find the last row with text.
To find the last row what you are actually doing is going to excel, select the last row (1048576) and the column where it will have text, in this case 1 or column "A" and then pushing ctrl+Up excel and vba will get you to the last cell with text.
To do that you use Cells(Row, column) instead of manually inserting row 1048576 you can just use rows.count and it will be the same.
Once you get the last row you just iterate with a For iloop meaning For a variable called i which equals 2 (For i = 2) To LastRow (to the last row you calculated) VBA will repeat the code in between the ForAnd Next adding 1 number to i everytime the loop restarts.
In this case is just adding a number to the rows on Cells(i, 3) so you can modify that cell depending of its i value.
I think you need to question why Excel needs to calculate on demand rather than automatically like normal. Failing that there are a few options
You could change your calculation method to Manual using the following in the ThisWorkbook object
Option Explicit
Dim xlCalcMethod As XlCalculation
Private Sub Workbook_Open()
With Application
' Store users current method for when closing the workbook
xlCalcMethod = .Calculation
.Calculation = xlCalculationManual
End With
End Sub
Private Sub Workbook_BeforeClose(Cancel As Boolean)
' Reset calculation
Application.Calculation = xlCalcMethod
End Sub
and then when the button is pressed use the following code to calculate placed in a Module
Option Explicit
Public Sub Button_Click()
Application.Calculate
End Sub
Another option to do this without looping would be:
Sub CalculateRange()
Dim rng As Range
' Update for your Range
With ActiveSheet
Set rng = .Range("C2:C" & .Cells(.Rows.Count, "A").End(xlUp).Row)
End With
rng.Value2 = Evaluate(rng.Offset(0, -2).Address & "*" & rng.Offset(0, -1).Address & "/100")
End Sub
Finally, the way you've come up with is perfectly acceptable as VBA

Wait until Excel finishes populating Bloomberg data using VBA

I have an Excel sheet with ~300,000 BDH formulas to download securities prices.
I want to
open the file and get all prices
paste them as values
save and close the file.
However, I do not know when Excel finishes populating Bloomberg data, so it's difficult to determine the time to do 2) and 3).
I have written VBA, but not sure if it works:
In Module1
Sub CheckFormulas()
If Application.CalculationState = xlDone Then
With Worksheets("Sheet1").UsedRange
.Value = .Value
End With
Else
Application.OnTime Now + TimeValue("00:30:00"), "CheckFormulas"
ActiveWorkbook.Close Savechanges:=True
End If
End Sub
In 'ThisWorkbook'
Private Sub Run()
Call CheckFormulas
End Sub
So the way it should theoretically work is:
I open the file
the code checks every 30 minutes if all BDH formulas are done
if they are done, then paste as values, save and close 4) if not, check 30 minutes later again.
I am wondering if this is the best way to accomplish my goal and want to know if Application.CalculationState is compatible or works with Bloomberg formulas BDH?
In our production environment we use a cell that checks if there are cells with "Req" in their formula:
=SUM(IFERROR(FIND("Req", _range_to_check_with_formulas_ ),0))
In a VBA Sub, we test the cell value with a WHILE LOOP:
while cell_to_test.value <> 0
Application.Calculate
Application.RTD.RefreshData
DoEvents
Wend
Call _sub_to_do_some_stuff_
Built on #stexcec's answer, since I do not want to add a test cell in the worksheet, I use VBA to search for "requesting" based on values. The following function is used to find "requesting" in the Range containing Bloomberg formulae:
Function IsFinished(ws As Worksheet) As Boolean
Dim i, j, LastRow, LastCol As Integer
Dim r, c As Range
LastRow = ws.Range("A1").End(xlDown).Row
LastCol = ws.Range("A1").End(xlToRight).Column
Set r = ws.Range(ws.Cells(1, 1), ws.Cells(LastRow, LastCol))
Set c = r.Find("Requesting", LookIn:=xlValues)
If c Is Nothing Then
IsFinished = True
Else
IsFinished = False
End If
End Function
Then, similar to #stexcec's answer, the following code to used to wait until all cells are refreshed:
' Wait until updated
Do While True
Application.Calculate
Application.RTD.RefreshData
DoEvents
If IsFinished(Application.ActiveSheet) Then
Exit Do
End If
Loop

Copy Check Box to Every 5th Cell with Command Button

I have an issue which i can't solve.I wrote this code:
Private Sub CommandButton2_Click()
Sheets("sheet2").OLEObjects("CheckBox1").Copy
Sheets("sheet3").Range("V7").PasteSpecial
End Sub
This code copy a checkbox from (sheet 2) to (sheet 3) starting from V7 cell. Now I want the next time I press the command button to paste the data to cell V12,next time to V17 etc. My vba knowledge is not very good as you can see.
This code will see how many checkboxes are already in the sheet you are pasting to and add 5 rows for each check box, then paste five rows under the last one.
Private Sub CommandButton2_Click()
' copy checkbox
Sheets("sheet2").OLEObjects("CheckBox1").Copy
Dim wks As Worksheet
Set wks = Sheets("Sheet3")
Dim cb As OLEObject, i As Integer
'determine how many boxes are already there and get count of cell to paste to
i = 7
For Each cb In wks.OLEObjects
If InStr(1, cb.Name, "CheckBox") Then i = i + 5
Next
'paste new checkbox
Sheets("sheet3").Range("V" & i).PasteSpecial
End Sub
Use a global variable. These must be at the top of your sheet, module, or form code above all subs and functions.
Then use that as the row number in your range. Range("V" & lRow)
Private lRow As Long
Private Sub CommandButton2_Click()
'Let's check if this is the first time the button has been used.
If lRow = 0 then
lRow = 7
Else
'Increment the row from the one we wrote to last time.
lRow = lRow + 5
End If
'Do the copy
Sheets("sheet2").OLEObjects("CheckBox1").Copy
Sheets("sheet3").Range("V" & lRow).PasteSpecial
End Sub
I dont know what data you got between in Sheet(3).Range("V7") and Sheet(3).Range("V12")
but juste before you're PasteSpecial, you shoud keep track where was the last time you paste data in Sheets("sheets3") in a specific cell in Sheet("sheets3"), in exemple : Sheets("Sheet3").Range("A1")
Then you'll be able to pastespecial to this cell 5 row under like this :
Sheets("sheet3").Range(Sheets("Sheets3").Range("A1").Offset(5,0)).PasteSpecial
right after that you update the Sheets("Sheets3").Range("A1") = Sheets("sheet3").Range(Sheets("Sheets3").Range("A1").Offset(5,0)).Address
So this should do the work :
Private Sub CommandButton2_Click()
Dim oWsSource as Worksheet
Dim oWsDestination as Worksheet
Set oWsDestination = ThisWorkbook.Worksheet("Sheets3")
Set oWsSource = ThisWorkbook.Worksheet("Sheets2")
'Do the copy
oWsSource.OLEObjects("CheckBox1").Copy
oWsDestination.Range(oWsDestination.Range("A1").Value).Offset(5,0)).PasteSpecial
oWsDestination.Range("A1").Value = oWsDestination.Range(oWsDestination.Range("A1").Value).Offset(5, 0)).Address
End Sub
All the answers put the first checkbox but the next one put it again to the same cell as before.I don't know if its matter but I use excel 2010.

Resources