I have two excel columns in a worksheet, consider as A(left) and B(right) and I have recorded a macro where it will calculate a formula and copy/paste it to all the right side columns till where the left side column has data. but when next time some extra data is added to the left column and when I run a macro to copy/paste then it is only considering the previous range but not extending to the newly added cells.
example : A1:A5 is left side and B1:B5 is the right side and my formula in B range which is right range calculate based on A1:A5 and my macro works fine and restricted only to B1:B5 even when I added new data like A1:A10 only copying B1:B5. what is the method I can use my macro automatically till the data range of A side column?
Better next time, you provide a screenshot of your data & also VBA code in question.
You are using a static range, while you require is dynamic range.
try this
Sub test()
Dim i As Integer
i = WorksheetFunction.CountA(Range("A:A"))
Range("B1:b" & i).Select 'instead of selecting you can provide your formula to whole range.
End Sub
For any other issue, feel free to comment
As per your description just try below.
Sub FillFormula()
Dim i As Long
i = Range("A1").End(xlDown).Row
Range("B1").FormulaR1C1 = "=RC[-1]+5"
Range("B1").AutoFill Destination:=Range("B1:B" & i)
End Sub
Related
I have a structured table in excel 2016.
I want to have a cell to count the number of cells across the entire row within the table if it matches my criteria.
I have tried putting this formula in column A on each row =COUNTIF(Table[#],"my criteria") but that does not count properly.
However, this works: =COUNTIF(Table[#[ColB]:[ColH]],"my criteria"). But since my table will expand, I don't want to specify the column name [ColB], I want to refer to the entre row in the table.
A header
countif
colC
colD
colE
First
formula
A
C
Second
formula
B
C
formula = =COUNTIF(Table[#],"A") does not work
formula = =COUNTIF(Table[#[colC]:[colE]],"A") works
My table will expand both horizontally and vertically.
Please Note: This solution is only available if you chose to use VBA. VBA does not work in web versions of Excel. Please ensure that you resave your workbook as a macro-enabled workbook before proceeding.
You can choose to use VBA and create your own custom worksheet formula. Since this question didn't start out as a VBA issue, I will be a bit more detailed on the process of setting this up as opposed to just throwing you some code and you having to figure out what to do with it.
After you've re-saved your workbook as a macro-enabled workbook, open the VBA Editor (VBE) by pressing Alt and F11 simultaneously.
In the VBE, click Insert > Module. You should now see Module1 highlighted on the left side bar (The project Explorer).
Copy and paste the following code in the blank area of the module:
Option Explicit
Public Function GetMyRowCount(Criteria As Variant) As Long
Dim ws As Worksheet
Dim tblRng As Range, RowRng As Range
With Application.Caller
Set ws = .Worksheet
Set tblRng = ws.Range(.ListObject.Name)
Set RowRng = ws.Range(ws.Cells(.Row, .Column + 1), ws.Cells(.Row, tblRng.Columns.Count))
End With
GetMyRowCount = Application.WorksheetFunction.CountIf(RowRng, Criteria)
End Function
Now use this UDF (User Designed Function) in your worksheet. In the column you would like the calculation to be in, simply type =GetMyRowCount("My Criteria") and it should calculate.
To point out how this code works in more detail:
Application.Caller is referring to the cell that this function is located in. Because we now know the location of the cell, VBA can use it's location to obtain the row data from it (which is why you don't need an argument for the row #).
RowRng is getting the starting point of the column within the ws.Range(...) function with the first ws.Cells(...) function. .Row is the row # from the GetMyRowCount function (using Application.Caller.Row method), and the 3 is simply the static column C.
The way we grab the last column we need is by counting the total # of columns within the table: ws.Cells(.Row, tblRng.Columns.Count)
Using the information we obtained from bullets 2 and 3, we can establish the entire range of the lookup we need, and then place this range into your CountIf() function, along with the criteria you passed with the function's argument:
GetMyRowCount = Application.WorksheetFunction.CountIf(RowRng, Criteria)
As you can see in the following example, I wanted to count the number of times in the row the number 1 occurred:
Another example showing it works with text as well by using "Apple" as the criteria:
Try this: =COUNTIF(B:B,"my citeria"), so if your Column is A, range would be A:A, for B it is B:B.
Let me know if this helps.
I'm using a PivotTable that will eventually have its values pasted to a separate workbook. The issue is that the filter tab is blocking the first row, the second row is blank and I don't need the headers from the third row. I also don't need the first 3 columns as they are not needed for the report.
The data I work with changes weekly so the number of rows will vary.
'Equitable is the name of the worksheet which was declared earlier in the code
Dim BuysPivot As Worksheet
Dim SummarySCS As Worksheet
Set BuysPivot = Equitable.Sheets("Buys Pivot")
Set SummarySCS = Equitable.Sheets("SCS_Summary")
Dim PivotCt As Long
PivotCt = BuysPivot.Cells(Rows.Count, "D4").End(xlDown).Row '---> Code fails
'1004 error. "Application-defined or object-defined error"
BuysPivot.Range("D4:H" & PivotCt).Copy
SummarySCS.Range("c2").PasteSpecial xlPasteValues
The code above should be able to Copy from D4 and down and paste it into the corresponding worksheet.
Thank you in advance for your assistance
Try
PivotCt = BuysPivot.Cells(Rows.Count, "D").End(xlup).Row
You are trying to start at the very bottom cell and then go down. Instead you start at the bottom and work up to find the first non-empty cell.
And your syntax was a little off - Cells is row, column.
sorry for being a total noob in excel!
I have two sheets, sheet 1 named "Stocks" and sheet 2 named "Stocks search".
In "Stocks" I have from A1 to B700 values. In A column I have the stocks symbols and in B column I have the stocks' issuers symbols, so every entry in A column is unique, yet there can be repeating entries in column B.
So in sheet "Stocks search", if I enter in A1 an issuer's symbol, I want for the formula to go search in sheet "Stocks" and fetch all stocks that this issuer has in new rows.
How can this be done in a formula? Thanks in advance!
This is a VBA solution to the question. IMHO, this is more appropriate than a formula (in this case). The formula approach is OK, but there are drawbacks - you have to remember the CSE rule, and then copy the formulas down the right number of rows (which you don't know in advance), etc, etc.
This code uses the same assumptions as the formula approach.
1 - sheets = Stocks and Stock report
2 - Data in Sheets, columns A and B (header in row 1)
3 - lookup code is on Stock report
4 - Output is on Stock report
One of the advantages is that if new data is added to the Stocks sheet (i.e. the bottom row > 700), the vba automatically adjusts.
The code is self-documented. But the essence is that it creates an autofilter on "Stocks" using the lookup value as the criterion; copies the rows that meet the criteria; and pastes the result to an output range on "Stock reports". The output range is cleared before the copy/paste takes place so that there are no left-overs from any previous lookup.
I think there's something to be said for creating a dropdown list for the lookup cell. No doubt that could be automated too by getting the codes from Column A, getting the unique values, and then apply them to the lookup cell. Just a thought;)
Sub so_52537740()
' CREDITS
'
' Refer: https://stackoverflow.com/questions/17531128/copy-paste-calculate-visible-cells-from-one-column-of-a-filtered-table
' Date: 8 July 2013
' Submitted by: Jon Crowell (https://stackoverflow.com/users/138938/jon-crowell)
Dim src As Worksheet, tgt As Worksheet
Dim filterRange As Range, copyRange As Range
Dim lastRow As Long
Dim stocks As String, stockreport As String
' set values for sheet names
stocks = "Stocks"
stockreport = "Stock report"
' set values for Sheet variables
Set src = ThisWorkbook.Sheets(stocks)
Set tgt = ThisWorkbook.Sheets(stockreport)
' clear the exist target data
tgt.Range("A4:B" & Rows.Count).ClearContents
' turn off any autofilters that are already set
If src.AutoFilterMode Then src.AutoFilter.ShowAllData
' find the last row in the Stocks sheet with data in column A
lastRow = src.Range("A" & src.Rows.Count).End(xlUp).Row
' the range that we are auto-filtering (all columns)
Set filterRange = src.Range("A1:B" & lastRow)
' the range we want to copy (only columns we want to copy)
' in this case we are copying both columns A and B
' we set the range to start in row 2 to prevent copying the header
Set copyRange = src.Range("A2:B" & lastRow)
' filter range based on column A being equal the the value in Cell A1 of the stockreport
' consider making this a dropdown list so that there are no errors
filterRange.AutoFilter field:=1, Criteria1:=Format(Sheets(stockreport).Range("a1").Value)
' copy the visible cells to our target range
' note that you can easily find the last populated row on this sheet
' if you don't want to over-write your previous results
copyRange.SpecialCells(xlCellTypeVisible).copy tgt.Range("A4")
' turn off any autofilters that are already set
If src.AutoFilterMode Then src.AutoFilter.ShowAllData
End Sub
Giving due credit: There is, as they say, nothing new under the sun. I have based this answer on an excellent piece of work by Jon Crowell on a question in StackOverflow "Copy/Paste/Calculate Visible Cells from One Column of a Filtered Table" in July 2013. Just goes to show what a bit of Googling and perseverance can achieve.
I believe I have an answer for you.
Try
=IFERROR(INDEX('Stocks Search'!$A$1:$A$700,SMALL(IF('Stocks Search'!$B$1:$B$700=$A$1,ROW('Stocks Search'!$A$1:$A$700)-MIN(ROW('Stocks Search'!$A$1:$A$700))+1),COLUMNS($A$1:A1))),"")
This is a CSE formula. What that means is once you enter it into cell B1, you will need to press Control+Shift+Enter. Once you do this, these brackets will appear around your formula {}
Click the fill button in the bottom right of the cell and drag the formula to the right (you will need to do this for as many cells as it is possible for answers). So if Company A has 40 possible answers, you will need to have this formula go at least 40 cells to the right.
The application of CSE formulas can be tricky. Essentially you need to go to the end of the formula in the formula bar, and then use Control+Shift+Enter.
I hope this helps.
I have a spreadsheet with a large amount of data in. About half the cells are merged horizontally with other cells and contain names e.g. John Doe.
Does anyone know how to write a macro to unmerge the cells while distributing the value of the cell to all the cells that were previously merged?
Cheers
Jack
EDIT: The reason I am doing this is to check to see if two adjacent cells are equal i.e. is A1 = A2. But I run into problems when either cell is merged. If anyone knows a way around this problem without separating the cells and copying the data that would be even better!
The idea I provide below is tested for Excel 2010 VBA Win7. However, being not sure I hope it should work as for Mac, too (as this is rather set of standard properties and methods of Range object). If this doesn't work please let me know to delete my answer.
This simple code will work for selected area however it's quite easy to change it to any other range. Some other comment inside the code below.
Sub Unmerging_Selection()
Dim tmpAddress As String
Dim Cell As Range
'change Selection below for any other range to process
For Each Cell In Selection
'check if cell is merged
If Cell.MergeCells Then
'if so- check the range merged
tmpAddress = Cell.MergeArea.Address
'umnerge
Cell.UnMerge
'put the value of the cell to
Range(tmpAddress) = Cell
End If
Next
End sub
And the picture presenting before and after result:
I was able to get the solution from KazJaw to work on a mac with one edit, changing Cell.UnMerge to
ActiveSheet.UsedRange.MergeCells = False, as provided by Ron Debruin here: http://www.rondebruin.nl/mac/mac027.htm.
Sub Unmerging_Selection()
Dim tmpAddress As String
Dim Cell As Range
'change Selection below for any other range to process
For Each Cell In Selection
'check if cell is merged
If Cell.MergeCells Then
'if so- check the range merged
tmpAddress = Cell.MergeArea.Address
'umnerge
ActiveSheet.UsedRange.MergeCells = False
'put the value of the cell to
Range(tmpAddress) = Cell
End If
Next
End sub
I'm trying to create a simple macro that copys the two first numbers in each cell in a column and printing them in a different column. This is in a excel-document with more than 1 worksheet. I've tried for a while to write the code, but with no prior experience, I have a hard time figuring out what to do. I know the "left()"-function is able to do this, but I don't know how I define which column to draw data from and to which column it will be printed. Any help will be greatly appreciated.
With no prior experience to writing VBA code, I am going to reccommend you stick to the formula method of doing. Honestly, even if you were familiar with VBA, you might still opt to use the formula.
A formula is put into the actual cell you want the value to be copied.
=LEFT(sourceCell, #of characters you want)
This is how it would look:
=LEFT(Sheet1!A1, 2)
Think of it as saying "this cell shall equal the first n characters in cell OO, starting from the left".
Once you are done with your formula, if you don't need it to be binded to the source anymore (if the sourceCell changes, so does the cell with the LEFT formula), you can highlight the cells, Ctrl + C to copy, then right-click and select Paste Special. Then select VALUE and hit OK and now the cells are hard-coded with the value they were showing, as if you typed it yourself.
Once you master using formulas, the next step is VBA. Don't go confusing yourself by jumping into VBA and writing code for ranges, etc. if you aren't comfortable with using =LEFT yet. One step at a time, and you'll be a pro before you know it. :)
Here is a quick sample sub to get you started:
Public Sub LeftSub()
Dim SourceRange As Range, DestinationRange As Range, i As Integer
'Define our source range as A1:A10 of Sheet1
Set SourceRange = Sheet1.Range("A1:A10")
'Define our target range where we will print.
'Note that this is expected to be of same shape as source
Set DestinationRange = Sheet1.Range("B1:B10")
'Iterate through each source cell and print left 2 bits in target cell
For i = 1 To SourceRange.Count
DestinationRange(i, 1).Value = Left(SourceRange(i, 1).Value, 2)
Next i
End Sub
How about
Sub foo()
Dim cell As Range
Dim sourceRange As Range
'//define the source column - looks for contiguous downward data from A1;
Set sourceRange = Range(Sheets("Sheet1").Range("A1"), Selection.End(xlDown))
'//iterate each cell
For Each cell In sourceRange
If IsEmpty(cell.Value) Then Exit For
'//example to place the value in corresponding row of column B in sheet 2
Sheets("Sheet2").Range("B" & cell.Row).Value = Left$(cell.Value,2)
Next
End Sub
Or an equivalent formula (in the destination cell)
=LEFT(Sheet1!A1,2)