code to count columns - vba

How do I select the last column from second row and move the cursor one cell above.
For eg. if I am at cell A2, how do I make macro to count the number of columns starting from Row 2 and select the cell above it.

The following will count the number of columns on row 2 and then select the cell above that one:
Sub foo()
Dim Lastcol As Long
Dim ws As Worksheet: Set ws = Sheets("Sheet1")
'declare and set your worksheet, amend as required
Lastcol = ws.Cells(2, ws.Columns.Count).End(xlToLeft).Column
'above count the columns on row 2
ws.Cells(1, Lastcol).Select
End Sub
Similarly to Count the number of Rows on a given column:
LastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
'get the last row with data on Column A

to "select the last column from second row and move the cursor one cell above", just use
Cells(2, Columns.Count).End(xlToLeft).Offset(-1).Select
of course, what above is implicitly referring to currently active worksheet in currently active workbook

Related

Formatting as a table dynamically Excel VBA

I would like to format a certain range in a worksheet as a table in Excel. The formatting will always start in row 10.
In order to do so, I have written the following code:
Set rng = Range(Range("B10"), Range("B10").End(xlUp).SpecialCells(xlLastCell))
Set table = Sheets("Results").ListObjects.Add(xlSrcRange, rng, , xlYes)
table.TableStyle = "TableStyleMedium13"
As of now, the formatting is done from row 10 until the end of the worksheet - even in empty rows. However, I would like the table to be formatted only up until the last row of data and for it to do this dynamically given the fact that the amount of data will vary. How can I do this?
The code below will format all cells from "B10" until last row with data in Column B (it will also format blank rows in the middle, in case you have gaps).
Dim LastRow As Long
With Sheets("Results")
' find last row with data in Column B
LastRow = .Cells(.Rows.Count, "B").End(xlUp).Row
' set Rng from B10 untill last row with data in Column B
Set Rng = Range("B10:B" & LastRow)
Set Table = .ListObjects.Add(xlSrcRange, Rng, , xlYes)
Table.TableStyle = "TableStyleMedium13"
End With
Range("B" & Rows.Count).End(xlUp)
This should work - will simply identify last populated row.

VBA search column heading in a sheet and return SUM in another sheet

I would like to get datas from sheet 1 to sheet 2 with reference to the column headings With VBA.
For example:(EXCEL file)
So if I want to find the sum of fun1 person A with criteria 1 the command have to go and find the heading “sum of fun 1” in sheet 1 and choose the datas that are only under criteria 1 and sum it up in sheet 2 cell D5. (By using column heading reference instead of cell reference. The table range is A2 : U80. thanks.
Public Sub Match()
ThisWorkbook.Sheets("Sheet1").Activate
Range("Sheet2!B3") = Application.Sum(Application.Index(Range("A:G"), 0, Application.Match("Crit1" & "Fun1personA", Range("A2:G2"), 0)))
End Sub
I have tried it codes but it failed. i know that i havnt include the Row reference for crit1 , but iam not sure how to apply that to the formula.
Can anyone help me with this ? Thanks in advance
You could do it with a formula.
I'll assume that the table in your example covers the range A1:E10.
First we'll need to find the correct column using a MATCH formula:
=MATCH("Fun2PersonA",$1:$1,0) - this will return 3 as Fun2PersonA is in column C.
Next we need to know how many rows are in the table. Assuming the criteria in column A has no blanks except cell A1 we can use COUNTA:
=COUNTA($A:$A)+1 - this will return 10.
The above two formula will be used a few times within the final result, so will probably be easier to use helper cells to store the results (I'll just call them ColumnRef and LastRowRef for readability rather than actual cell references).
Now to set a reference to the first cell and last cell in column C.
=INDEX($1:$1,,ColumnRef) will reference the header, while =INDEX($1:$1048576,RowRef,ColumnRef) will reference the last cell.
As these can be used as references and not just values =SUM(INDEX($1:$1,,ColumnRef):INDEX($1:$1048576,RowRef,ColumnRef)) will sum everything in that column. It's the same as writing =SUM(C1:C10).
But you want to use SUMIF, so we need to reference the criteria in column A as well.
=INDEX($A:$A,RowRef) will reference the last cell in column A, so $A$1:INDEX($A:$A,RowRef) will reference all values in column A.
Final Formula:
The final step is to stick it all together into your final formula:
=SUMIF($A$1:INDEX($A:$A,RowRef),"Crit1",INDEX($1:$1,,ColumnRef):INDEX($1:$1048576,RowRef,ColumnRef))
This is the same as writing =SUMIF($A$1:$A$10,"Crit1",$C$1:$C$10)
For a VBA solution:
Public Function SumCriteria(FunPerson As String, Criteria As String) As Double
Dim rTable As Range
Dim rCol As Range
Dim rCriteria As Range
Dim LastRow As Long
Dim LastCol As Long
'Update Sheet1 to the sheet name with your table.
With ThisWorkbook.Worksheets("Sheet1")
'You may have to change how to find the last row/column depending
'on any extra data on the sheet.
LastRow = .Cells(Rows.Count, 1).End(xlUp).Row
LastCol = .Cells(1, Columns.Count).End(xlToLeft).Column
Set rTable = .Range(.Cells(1, 1), .Cells(LastRow, LastCol))
'EDIT: You could set your table as below if it's a static size.
'Set rTable = .Range("A2:U80")
'The first statement finds the FunPerson heading
Set rCol = rTable.Rows(1).Find(What:=FunPerson, LookIn:=xlValues, LookAt:=xlWhole)
If Not rCol Is Nothing Then
SumCriteria = Application.WorksheetFunction.SumIf(rTable.Columns(1), Criteria, rTable.Columns(rCol.Column))
Else
SumCriteria = CVErr(xlErrValue)
End If
End With
End Function
This method looks at column A and row 1 to get the dimensions of the table and then uses SUMIF to count the figures.
You can use it as a worksheet formula: =SumCriteria("Fun1PersonA","Crit1")
or within VBA:
Public Sub Test()
Dim a As Double
a = SumCriteria("Fun1PersonA", "Crit1")
End Sub

Excel VBA - Delete Rows Based on Criteria

I have a report that I pull everyday that is placed in a very awekward format. It's contains a variable row count by 4 columns organized into unofficial tables based on the Name of each employee.
What I have is an employee name in column B preceded 2 blank rows above and followed by 1 blank row of data below.
What I want to accomplish is loop through the data, identify cells in column B <> blank, delete the entire 2 rows below that cell, and delete the entire 1 row above that cell.
Below is what I have so far. not much:
Sub test()
Dim currentSht As Worksheet
Dim startCell As Range
Dim lastRow As Long
Dim lastCol As Long
Dim i as integer
Set currentSht = ActiveWorkbook.Sheets(1)
Set startCell = currentSht.Range("A1")
lastRow = startCell.SpecialCells(xlCellTypeLastCell).Row
lastCol = startCell.SpecialCells(xlCellTypeLastCell).Column
For i = lastRow To 1
If Cells(i, "B").Value <> "" Then
End Sub
without making major changes to your code, try this:
For i = lastRow To 1 Step - 1
If Cells(i, "B").Value <> "" Then
Range(Cells(i, "B").Offset(1), Cells(i, "B").Offset(2)).EntireRow.Delete 'delete two below
Cells(i, "B").Offset(-1).EntireRow.Delete ' delete one above
You already get to your non-blank cell (ie Cells(i,"b")). To reference a range in relation to a cell you already have, use OFFSET.
So, and in this order, you select a range of cells from one below your cell Offset(1) to two cells below Offset(2)'. Change this range toENTIREROW` for those cells, and delete.
Then you select the cell above Offset(-1), select the ENTIREROW and delete.
as per your question narrative you'd possibly need to delete all rows that has a blank cell in column "B"
should that be the issue than you could (disclaimer: test it on a copy sheet!) simply go like follows:
Sub test()
With ActiveWorkbook.Sheets(1)
.Range("A1", .Cells(.Rows.Count, "A").End(xlUp)).Offset(, 1).SpecialCells(xlCellTypeBlanks).EntireRow.Delete
End With
End Sub

Selecting range without knowing number of rows or columns having data in Excel/VBA

I am looking for code for two different types of selection. One code would select in an L shape all of the rows in one column and all of the columns in one row. In the example of having data in the range A1:A10, and data in row 10 only from col A - K. The selection would look like an L. How can you do this without knowing how many rows or columns have data in them?
The second code would have the same data, but need to select the whole range A1:K10 in that example, but the code would need to select whatever range had the data.
i found the answer. i have to do a union. here is the code with the union at the end.
Sub mywork()
Dim ws As Worksheet
Dim lRow As Long, lCol As Long
Dim rng As Range
'~~> Set this to the relevant worksheet
Set ws = [Sheet1]
With ws
'~~> Get the last row and last column
lRow = .Range("A" & .Rows.Count).End(xlUp).Row
lCol = .Cells(lRow, .Columns.Count).End(xlToLeft).Column
'~~> Set the range
Set rng = .Range(.Cells(lRow, 1), .Cells(lRow, lCol))
End With
Set rng = Application.Union(Range("A1:A" & lRow), rng)
rng.Select
End Sub
activesheet.usedrange.address should tell you the used range.
In your case something like this should work: [sheet1].usedrange.select (Replaces all the code in the module)
The benefit here is the fact that you are not hard coding "A1:A" against the last identified cell, works well if you have blank rows at the top.

If The cell has values, select the same quantity of lines in another Sheet

In my first sheet I insert 389 lines of text, it makes a process and appears in sheet 3 fully processed, but I need to select the same number of lines in the Sheet 3, then copy it.
The main problem is that the quantity of lines that I insert in the first sheet can be from 1 to 10,000.
If you are inputing your data such that each line is filled from the first line down to some line you can find the last row number with the following, where "A" is the column the data is in.
Dim sht As Worksheet
Set sht = ThisWorkbook.Sheets("Sheet1")
lastrow = sht.Cells(sht.Rows.Count, "A").End(xlUp).Row
Then you can go through the data with a loop like:
For each cell in sht.Range("A1:A" & lastrow)
'do something with cell
next cell