How do I increment cell in Excel VBA script? - vba

I have a data in excel which I want to make a VBA script to copy it into a new worksheet but in a different way.
For example, I have this in sheet1 in A1~A3 cells.
Adam(A1)
Sam(A2)
Smith(A3)
I want to use these cells and create the following in another worksheet using refedit control.
Adam(A1)
Adam(A2)
Adam(A3)
Adam(A4)
Sam(A5)
Sam(A6)
Sam(A7)
Sam(A8)
Smith(A9)
Smith(A10)
Smith(A11)
Smith(A12)
I have refedit control in place in VBA script, but I'm not sure how to increment cell numbers to make it copy and paste into a new worksheet. I would like to use refedit control so that I can assign any cells and make it copy and repeat itself. How do I do this in VBA script?

Check out the Range Rows, Cells, and Address properties. This should help. Your question is too vague for a direct answer.
(This will get you started.)
Range.Row Property
http://msdn.microsoft.com/en-us/library/bb221550(office.12).aspx
Returns the number of the first row of the first area in the range. Read-only Long.
Example
For Each rw In Worksheets("Sheet1").Rows
If rw.Row Mod 2 = 0 Then
rw.RowHeight = 4
End If
Next rw

To increment cells in Excel VBA, you can use the Offset-property of the Range-object, e.g.
ActiveCell.Offset(1, 1).Select
will select the cell one row down and one column to the right of the active cell.

To add to Geoffrey's answer about active cell - it would also require that you activate the sheet you are looking to input your values if it is a different sheet from the one that is currently active. Additionally you would have to activate a cell to use activecell and the activecell offset property.
For example
'Activates the name of the sheet you would like to activate
Sheets("Sheet2").Activate
'Activates cell A1
Range("A1").Activate
'Activates cell one row down, one column right
ActiveCell.Offset(1,1).Select
'if current sheet is not activate you just do Sheets("Sheet2").Range("A1").Activate
The offset property of ActiveCell refers to other cells based off of the current active cell.
For example-
Offset(row,column) -
First Argument -Positive values as the first argument refer you to rows below the current active cell and Negative values refer you to rows above the current active cell
Second Argument-Positive values as the second argument refer you to columns right of the current active cell and Negative values refer you to columns left the current active cell

Related

Only change values on active worksheet

I have a workbook with 4 sheets. The 4 sheets are almost identical Some of the cells values are calculated by calling a macro in the cell. For the active worksheet this Works fint. The macro gets all the values from the correct sheet and the calculation is correct.
But, when the calculation is done in the active worksheet the cells in all the worksheet that calls the macro is changed with the value calculated in the active worksheet.
How do I make sure that only the cells in the active workseet that calls the macro is changed?
[EDIT]
Example:
I have 2 sheets.
In both sheets I have a cell that calls a function: .Value = "=FunctionName()"
When I do calculations in sheet 1, the cell with the call is showing correct result. But the cell in sheet 2 is showing the same result.
Only the cell in sheet 1 should show the result from the function calculated from sheet 1.
Say if you want to change in sheet1. Then
Worksheets("Sheet1").Activate
With ActiveWorksheet
Call calculationsmacro 'your macro to calculate the cells
End With
I had kind of similar problem and it was solved by this method.
If it works for you then it would be really grateful if you can mark my answer.

Copy variable range on one sheet to next empty row on another sheet

I need to copy all data in columns P:Y and paste it into the next blank cell in column A.
I've written the code below, which works fine, except that the data it is copying (P:Y) contains a formula down the whole column and although I am pasting values in order to only get the value returned, it is counting all cells as containing data.
By this I mean that when I run the macro the first time, it works. But when I run it a second time, (which I need to do) when it finds the last empty row. It isn't the last empty row! It selects a row far below the actual last row that I can see data in.
There is no data in the empty rows and no formula in them, but for some reason that is beyond me, it is treating the rows as not empty.
The data returned in columns P:Y by the formula will change every month, so I can't define a specific range.
How can I modify the code to rectify this - or is there a better way I could do this?
Sub SelectRangea()
Sheets("Set Up Data").Select
Range("P2:Y10000").Select
Application.CutCopyMode = False
Selection.Copy
With Sheets("Pasted Report")
lst = .Range("A" & Rows.Count).End(xlUp).Row + 1
.Range("A" & lst).PasteSpecial xlPasteColumnWidths
.Range("A" & lst).PasteSpecial xlPasteValues
End With
End Sub
When a cell contains a formula, it will have a value, even though it seems empty when inspecting the cell on the sheet. So if you copy such seemingly empty cells and paste them somewhere else (even if only as values), the pasted-to cells now do contains something (i.e. they're not really empty anymore; they're an empty string to be exact instead of VBA's Empty).
Range.End will then move to those last empty cells instead of moving to the last true filled cell.
You can see this for yourself if you do this by hand on an empty sheet: enter in A1:A5 the formula ="", then copy the range as values to B1:B5, then select B10 and press Ctrl-Up.
A fix would be to use the Range.End method, and then just inspect the cell contents going upwards. Or use Range.Find, but keep in mind that that also alters the settings in the user's Find dialog.

Print dynamic Excel page with changing content

I have an Excel workbook with two worksheets.
On the first one I have a "form" and on the second all the data in a table.
What I have done is that on the first sheet I change an ID number, then a function looks at the second sheet to find the ID number and then changes the data on the cells I've specified to those on the second page.
It is for paying company employees and there are currently 50 unique ID's.
Is there a way to print the first sheet with different content in one click if possible? Does anyone know a way to do this?
You can use something like this For each myCell in worksheets(2).range("A1:A50")...next myCell to loop through all the stored cells with different ID's and put each of the value to the cell on the sheet 1.
This is what I mean
Sub PrintAll_IDs()
For Each myCell In Worksheets(2).Range("A1:A50") 'range with stored ID's
Worksheets(1).Range("A1") = myCell.value ' "A1" is the cell with ID that you change manually now
Worksheets(1).PrintOut ' I'm not sure how to print using VBA, just showing the workflow
Next myCell
End Sub

Meaning of .Cells(.Rows.Count,"A").End(xlUp).row

I was just wondering if you could help me better understand what .Cells(.Rows.Count,"A").End(xlUp).row does. I understand the portion before the .End part.
It is used to find the how many rows contain data in a worksheet that contains data in the column "A". The full usage is
lastRowIndex = ws.Cells(ws.Rows.Count, "A").End(xlUp).row
Where ws is a Worksheet object. In the questions example it was implied that the statement was inside a With block
With ws
lastRowIndex = .Cells(.Rows.Count, "A").End(xlUp).row
End With
ws.Rows.Count returns the total count of rows in the worksheet (1048576 in Excel 2010).
.Cells(.Rows.Count, "A") returns the bottom most cell in column "A" in the worksheet
Then there is the End method. The documentation is ambiguous as to what it does.
Returns a Range object that represents the cell at the end of the region that contains the source range
Particularly it doesn't define what a "region" is. My understanding is a region is a contiguous range of non-empty cells. So the expected usage is to start from a cell in a region and find the last cell in that region in that direction from the original cell. However there are multiple exceptions for when you don't use it like that:
If the range is multiple cells, it will use the region of rng.cells(1,1).
If the range isn't in a region, or the range is already at the end of the region, then it will travel along the direction until it enters a region and return the first encountered cell in that region.
If it encounters the edge of the worksheet it will return the cell on the edge of that worksheet.
So Range.End is not a trivial function.
.row returns the row index of that cell.
[A1].End(xlUp)
[A1].End(xlDown)
[A1].End(xlToLeft)
[A1].End(xlToRight)
is the VBA equivalent of being in Cell A1 and pressing Ctrl + Any arrow key. It will continue to travel in that direction until it hits the last cell of data, or if you use this command to move from a cell that is the last cell of data it will travel until it hits the next cell containing data.
If you wanted to find that last "used" cell in Column A, you could go to A65536 (for example, in an XL93-97 workbook) and press Ctrl + Up to "snap" to the last used cell. Or in VBA you would write:
Range("A65536").End(xlUp) which again can be re-written as Range("A" & Rows.Count).End(xlUp) for compatibility reasons across workbooks with different numbers of rows.
The first part:
.Cells(.Rows.Count,"A")
Sends you to the bottom row of column A, which you knew already.
The End function starts at a cell and then, depending on the direction you tell it, goes that direction until it reaches the edge of a group of cells that have text. Meaning, if you have text in cells C4:E4 and you type:
Sheet1.Cells(4,"C").End(xlToRight).Select
The program will select E4, the rightmost cell with text in it.
In your case, the code is spitting out the row of the very last cell with text in it in column A. Does that help?
.Cells(.Rows.Count,"A").End(xlUp).row
I think the first dot in the parenthesis should not be there, I mean, you should write it in this way:
.Cells(Rows.Count,"A").End(xlUp).row
Before the Cells, you can write your worksheet name, for example:
Worksheets("sheet1").Cells(Rows.Count, 2).End(xlUp).row
The worksheet name is not necessary when you operate on the same worksheet.

Active cell as input to formula

I was wondering if I can use the active cell, by that I mean the cell that is "highlighted" at a given time with the square border after there was a mouse click there, as an argument in a function.
For example, I have created a table with weighted averages with 3 weights: w1 is given in the column headers (kindly see the file below), w2 in the row headers, and w3 which complements w1 and w2 to 1.
What I'd like to do is have cells outside the table show the weights the average got when a cell in the table is selected.
For example:
Screenshot: http://imgur.com/emmBH5S/
file can be found here: https://drive.google.com/file/d/0B_7-00fdslR7Tm11ODRVS296ckk/
Here we see the cell K12 is active,
and for K12 w1=0.2, w2=0.15, and so, the cells in the weights tables above (rows 3-4) get the appropriate values according to the weights in the active cell.
(of course I manually created this one for illustration purposes)
Is there a way to do that? Preferably without VBA if possible
Couldn't find anything very useful...
Thanks in advance!
A
You don't need VBA (although you may prefer it).
W1: =INDEX($F$8:$AA$29,1,MAX(COLUMN(INDIRECT(CELL("address")))-(COLUMN(F8)-1),1))
W2: =INDEX($F$8:$AA$29,MAX(ROW(INDIRECT(CELL("address")))-(ROW(F8)-1),1),1)
W3: =J4-(G4+H4)
The CELL function with the address argument returns the address for whichever cell is active. I use INDIRECT to convert that address (just a string) to a cell reference. Then I use
=INDEX(Range, 1, Column of Reference)
to get the w1 value - the value in the first row and the same column as the active cell. The formula doesn't care what cell you make active, so I stuck a MAX in there so it would return a zero if you're out of the range.
Note that simply selecting a cell won't trigger the change. Once you select a cell, press F9 to calculate the sheet to get the proper results.
You need to use VBA. Following your example place this code in your Sheet object
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Row > 8 And Target.Column > 6 Then
Range("G4").Value = Cells(8, Target.Column).Value
Range("H4").Value = Cells(Target.Row, 6).Value
Range("L4").Value = Cells(Target.Row, Target.Column).Value
End If
End Sub
Cell L4 shows your selected cell value which can be used in other formulas.
EDIT
To place your code you go to VBA window and double click on the Sheet object where you have your data. (Marked with an arrow in the picture)
Then paste yout code.