I have a row of cells A1:G1 on Sheet2 and I want those values on Sheet1 columns A:G but only on visible rows. I know how to do it through selecting visible cells only and pasting value from Sheet2. But I have many rows and it is incredibly slow. I tried creating an array from cells A1:G1 on Sheet2 and making it a 2D array and then selecting range on Sheet1 and set value in the worksheet but I cannot make the code to work at all. What other ways would you suggest?
Dim Arr() As Variant
Dim 2DArr() As Variant
Sheet1.range(cells(1,8),cells(last_row,8). select
activecell.formulaR1C1="=AGGREGATE(3,5,#columnA)"
Arr = Sheet2.Range("A1:G5")
for i=1 to last_row
if cell(i,8)=1 then
2DArr(i)=Arr
End If
Next i
Sheet1.range("A1:G900000")=2DArr
I admit this is an annoying one: Excel VBA does not have a Visible property for its ranges. Instead it has a Hidden property which works exactly in the opposite way, as you can see from this simple example:
' instead of if RAnge(A1).Visible, you should do:
if NOT(RAnge(A1).Hidden)
Related
I would like to have a subroutine that is passed a named range and a number of rows, and copies that number of rows from the bottom of the range and inserts them into the named range at the bottom, becoming the new bottom of the named range. If I have a range named 'WellC1', depicted here:
I would like the function to copy the bottom n rows (in this case, 12) and paste them (or insert them) at the bottom, while keeping them within the named range, so it ends up like this:
It should only paste the formulas (which is what is shown here as the 11.47 and numbers on the right are formula results) and needs to copy within the named range so the process can be repeated.
Im new to VBA and having severa problems with this. One is insert adds things above the insert point; to keep the new years' data in the named range I figured I could add the first row of the next well's data to the bottom of the range and insert there (so top row of Well C2 is actually the bottom row of Well C1s named range and inserting at it keeps the new Well C1 data in the well C1 range). I can get the insert-into-named-range thing to work fine if there's no merged cells, btw.
The other is I can't figure out how to actually copy the 12 (or n) bottom rows of named range WellC1, because of the merged cells. Is there a way to copy the bottom n rows of a range and/or reference them even if some are merged? What I've been trying so far is tweaking out versions of this:
Sub Copy_Insert_Into_Named_Range( _
target_range As Range, _
Optional num_rows As Integer = 1)
'This uses the top row of the next well range as the bottom of this named range to be able to use a copy/insert and keep it within the named range.
Dim last_row As Range: Set last_row = target_range.Rows((target_range.Rows.Count) - 1)
Dim top_row As Range: Set top_row = target_range.Rows((target_range.Rows.Count) - (num_rows + 1))
Dim num_targ_columns As Integer: num_targ_columns = target_range.Columns.Count
Dim upper_cell As Range: Set upper_cell = top_row.Cells(1)
Dim lower_cell As Range: Set lower_cell = last_row.Cells(num_targ_columns)
Dim copy_area As Range: Set copy_area = Range(upper_cell & ":" & lower_cell)
copy_area.Copy
last_row.Offset(1).PasteSpecial
I'm falling apart at the copy_area set, I think because of the merged cell being lower_cell. Is there a different way to select these 12 (or n) bottom rows of the named range? There's about 600 of these wells we do this to manually per project so I'd like to automate that. My core idea is have each well's area be a named range and step through each named range and run the copy/insert function for it. Its working in other projects that don't have merged cells. I appreciate any ideas!
I am working with tables in Excel (ListObject). I apply filter via VBA on a table which work fine. I would like to read specific row (or row, col) from filtered table. I tried with SpecialCells which return a range of cells. But I would like to iterate as rows like listobject.listrows(N) where n is number of row. I didn't find any example. Of course I can iterate cell by cell and locate the the row via formula. But I wonder if exist a better way.
For instance: I would like filter a table with several criteria and update certain columns with a particular value.
I hope I am clear with my question.
thanks.
You can loop rows like this
Option Explicit
Sub test()
Dim rng As Range
With ActiveSheet.ListObjects(1).DataBodyRange
For Each rng In .SpecialCells(xlCellTypeVisible).Rows
Debug.Print rng.Address
Next rng
End With
End Sub
I want to write a formula like =SUM(tab2!A:A) but instead use the column title of A which is say "count". How can I modify this to look more like: =SUM(tab2!"count")?
The reason I want to do this is because I copy and paste a spreadsheet from another source in tab2 and the column referring to "count" may be in a different column. I want the formula to give me the correct calculation as soon as I paste the new spreadsheet by automatically finding the column to sum up by title name.
I must be missing something because this seems like a very basic question and I can't find the answer anywhere...
Thanks for your help!
I like the idea of naming ranges proposed by #Doug, but if the issue is that you are dumping your data in [and you don't know in advance which column is going to be where] and would need to rename your range every time, there are other options - I suggest using OFFSET. OFFSET allows you to dynamically create a range, starting at a particular point and moving down/up / right/left for as many rows and columns as you determine.
In your case, you will need to combine that with a method for searching the columns to see which one says "Count". I am assuming that your column headings are always in row 1. If they aren't [or if they aren't always in row 2, or any row you know in advance]... you can get around that but then I'd recommend you try to make your data more uniform instead of creating unnecessary Excel workarounds.
In total your formula would look like this:
=SUM(OFFSET(A1,,MATCH("Count",1:1,0)-1,ROWS(A:A),1))
What this does is first determine which column the word "Count" is found in, in row 1. Then it subtracts 1 from that number - this now equals the number of columns to the right that it is, from column A. It uses offset to create a reference to that column, for all rows, and sums those rows together.
Check out the name manager for naming ranges :)
You didn't say whether you would consider a macro solution. If so, this may work.
If the sheet you are pasting into is Sheet2 and the sheet you want the result in is Sheet1, then this macro, if placed in the Worksheet_Activate event of Sheet1 will give you the result as soon as you click on the Sheet1 tab afetr pasting your data into Sheet2:
Private Sub Worksheet_Activate()
Dim r As Range
Dim rCol As Range
Dim rFound As Range
Dim ws As Worksheet
Dim lTotal As Long
Set ws = Sheet2
Set r = ws.Cells
Set rFound = r.Find("count")
If Not rFound Is Nothing Then
Set rCol = rFound.EntireColumn
lTotal = Application.WorksheetFunction.Sum(rCol)
End If
Cells(1, 1) = lTotal
End Sub
It does assume there is only one cell with the word "count" in it on Sheet2.
How would I go about highlighting rows which contain a cell that contains a name from a list of names which I can specify?
I assume this is best done by a macro, but not sure where to start.
Place this code in a module
Option Explicit
Public Sub ApplyConditionalFormattingsFromAList()
'
' this code create multiple conditional formattings on current selected cells
' using a list of conditions along with its formattings defined in another worksheet.
' to use, just select the range and then run this code
'
Dim iRng As Range
Dim ApplyToRng As Range
Dim wsCondition As Worksheet
' determine the worksheet that define the conditions and formattings
' to do this, create a blank worksheet and name it "Names",
' then in the worksheet,
' column A of the worksheet should contain the names to highlight, start at [A1]
' column B of the worksheet should be filled with the highlight color to apply, working in pair with column A
Set wsCondition = Worksheets("Names")
' i make the Macro to apply to current selection.
' i made it this way so that you can reuse this code on different sheets multiple times
' anyway, you can change this to apply to a fixed range, which can then be turned into automatic running code.
' e.g. Set ApplyToRng = Columns("B")
Set ApplyToRng = Selection
' clear the conditional formattings of current selection. otherwise the list of conditional formatting will keep growing.
ApplyToRng.FormatConditions.Delete
' add the conditions
For Each iRng In wsCondition.Range([A1].Address, wsCondition.Cells(Rows.Count, 1).End(xlUp))
ApplyToRng.FormatConditions.Add Type:=xlTextString, String:=iRng.Value, TextOperator:=XlContainsOperator.xlContains
ApplyToRng.FormatConditions(ApplyToRng.FormatConditions.Count).SetFirstPriority
ApplyToRng.FormatConditions(1).Interior.Color = iRng.Offset(0, 1).Interior.Color
ApplyToRng.FormatConditions(1).StopIfTrue = False
Next iRng
End Sub
The worksheet "Names" would look like this
I would write it as a macro.
Begin with the first sheet.
Find the last used column and the last used row on that sheet.
Use these figures to iterate through each cell in each row.
For each cell you iterate through you need to go to the list and iterate through each item in the list. Compare the cell value and the list value, if they are the same then highlight the row and go the next row.
I hope that 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