Macro code from Excel 2003 doesn't work in 2007 - vba

This code works well in Excel 2003 but fails in Excel 2007. What am I not seeing in it that crashes it? It errors out when it gets to the "LastRow =".. This is my error message:
Run-Time Error 13 Type Mismatch
Dim LastRow As Long
Dim LastColumn As Integer
Dim LastCell As Range, NextCell As Range
' ****************************************************
' Finds LastRow and LastColumn
With Worksheets("DB")
' Find Last Row/Col
If WorksheetFunction.CountA(Cells) > 0 Then
' Search for any entry, by searching backwards by rows
LastRow = Cells.Find(What:="*", After:=[A1], _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious).Row
' Search for any entry, by searching backwards by columns
LastColumn = Cells.Find(What:="*", After:=[A1], _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious).Column
End If
Set NextCell = Worksheets("DB").Cells(LastRow + 1, (LastColumn))
End With
' ****************************************************
Found an error. Guess I copied the Lastrow and was GOING to change the second one to columns. but that still doesn't solve the hang on the first chunk. Opps while editing that last part to columns I see that I may have typed an extra "s" in the .Rows Looks like it SHOULD be .Row I'll see when I get home since my hard copy at work shows no "s". Guess that's what I get when trying to "Remember" the code when I get home. To "s" or not to "s", that is the question. LOL At least I think I solved it with a little poke the the head. Thanks Siddharth.

Are you sure it works with Excel 2003?
You have to use .Row instead of .Rows. See This
Your code will also fail because your LastColumn=0
Is this what you are trying?
Sub Sample()
Dim LastRow As Long
Dim LastColumn As Integer
Dim NextCell As Range
With Worksheets("DB")
If WorksheetFunction.CountA(Cells) > 0 Then
'~~> Find Last Row
LastRow = Cells.Find(What:="*", After:=[A1], _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious).Row
'~~> Find Last Column
LastColumn = Cells.Find(What:="*", After:=[A1], _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious).Column
End If
'~~> Set the cell to the first empty cell after the last cell
'~~> which has data
Set NextCell = Worksheets("DB").Cells(LastRow + 1, (LastColumn))
'~~> Display the address of that cell
MsgBox NextCell.Address
End With
End Sub

Related

Paste column format only through iteration

I have a code that copies data from one workbook to another. Now, the 2nd column in my destination workbook has a certain color format that I need to be applied till the last column with data in it.
This is the code snippet to find the last non-empty column :
Dim rLastCell As Range
Set ws = ThisWorkbook.Sheets(DestName)
Set rLastCell = ws.Cells.Find(What:="*", After:=ws.Cells(1, 1), LookIn:=xlValues, _
LookAt:= xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlPrevious, MatchCase:=False)
Dim LastCol As Long
LastCol = rLastCell.Column
MsgBox LastCol
So, now I want to iterate and paste the format from the 2nd column to all the columns until LastCol. Any help would be appreciated.
This is the solution :
lCol = Cells(1, Columns.Count).End(xlToLeft).Column
MsgBox "Last Column: " & lCol
Dim x As Long
Columns(2).Copy
For x = 3 To LastCol
Columns(x).PasteSpecial Paste:=xlPasteFormats
Next

Deleting empty rows generates 1004 error

I want to delete rows, if cells in a certain column are empty.
I'm using the sample code I found here.
Initially, the cells in question were in column B. I used the following:
Sub delrowEmptyStr()
Dim EmpCol As Range, LstRw As Long
LstRw = Columns(2).Find(What:="*", SearchOrder:=xlRows, SearchDirection:=xlPrevious, LookIn:=xlFormulas).Row
Set EmpCol = Cells.Find(What:="*", SearchOrder:=xlColumns, SearchDirection:=xlPrevious, LookIn:=xlFormulas).Offset(, 1).EntireColumn
With Intersect(Rows("2:" & LstRw), EmpCol)
.FormulaR1C1 = "=IF(RC2="""",""X"","""")"
.Value = .Value
.SpecialCells(xlConstants).EntireRow.Delete
End With
End Sub
I reformatted and put that data in column A. I changed the Sub to the following:
Sub delrowEmptyStr()
Dim EmpCol As Range, LstRw As Long
LstRw = Columns(1).Find(What:="*", SearchOrder:=xlRows, SearchDirection:=xlPrevious, LookIn:=xlFormulas).Row
Set EmpCol = Cells.Find(What:="*", SearchOrder:=xlColumns, SearchDirection:=xlPrevious, LookIn:=xlFormulas).Offset(, 1).EntireColumn
With Intersect(Rows("2:" & LstRw), EmpCol)
.FormulaR1C1 = "=IF(RC1="""",""X"","""")"
.Value = .Value
.SpecialCells(xlConstants).EntireRow.Delete
End With
End Sub
Running this now yields 'Run-time error 1004: No cells were found'.
Hitting 'Debug' highlights the row
.SpecialCells(xlConstants).EntireRow.Delete
I did sort my data differently before running the 2nd iteration of the Sub - I'm wondering if maybe having all the empty cells I want to get rid of to the bottom of the column may be the issue?
I'm wondering if maybe having all the empty cells I want to get rid of to the bottom of the column may be the issue?
Yes, definitely, because the statement
LstRw = Columns(1).Find(What:="*", SearchOrder:=xlRows, _
SearchDirection:=xlPrevious, LookIn:=xlFormulas).Row
yields the LstRw as the last non-empty row in that specific column. You can fix this by simply finding the last non-empty row in your whole sheet instead of the last non-empty row in the specific column:
' vvvvvv
LstRw = Cells.Find(What:="*", SearchOrder:=xlRows, _
SearchDirection:=xlPrevious, LookIn:=xlFormulas).Row

Paste Data with AutoFill in VBA

I have the code below that copies the last column filled and paste it into the next empty, simple column. However I need the pasted column to be incremented (with autofill), in my case, with date. January> February> March and so on. Today it sticks with the fixed data.
Sub Test()
Dim ws As Worksheet
Set ws = ActiveSheet
Dim rLastCell As Range
Dim LastCol As Integer
Set rLastCell = ws.Cells.Find(What:="*", After:=ws.Cells(1, 1), LookIn:=xlFormulas, LookAt:= _
xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlPrevious, MatchCase:=False)
LastCol = rLastCell.Column
ws.Columns(LastCol).Copy ws.Columns(LastCol + 1)
End Sub

VBA - Problems dynamically selecting a range

I am new to VBA and am trying to write a macro that takes a workbook with several sheets of data and formats it for printing. Each sheet has tables of information (like operating/income statements). I want this code to be able to work for workbooks anyone creates but has the same basic information. This means I need to find start and end of the data on each sheet because it is not always in the same place (someone might start from "A1" and someone else from "B4", etc).
I've looked on the many websites for different ways to locate the first row used and last column used. What I have so far sometimes locates the starting row, ending row, starting column, and ending column correctly and other times it doesn't.
Sub FormatWorkbook()
Dim ws As Worksheet
Dim rowStart As Long
Dim columnStart As Long
Dim rowEnd As Long
Dim columnEnd As Long
Dim printStart As String
Dim printEnd As String
Application.ScreenUpdating = False
'Turn off print communication
Application.PrintCommunication = False
'Loop through sheets
For Each ws In Worksheets
'Make current sheet activesheet
ws.Select
'Set rowStart, columnStart, rowEnd, and columnEnd to the used range
With ActiveSheet
rowStart = .Cells.Find(what:="*", after:=.Range("A1"), LookAt:=xlPart, LookIn:=xlFormulas, searchorder:=xlByRows, searchdirection:=xlNext, MatchCase:=False).Row
columnStart = .Cells.Find(what:="*", after:=.Range("A1"), LookAt:=xlPart, LookIn:=xlFormulas, searchorder:=xlByColumns, searchdirection:=xlNext, MatchCase:=False).Column
rowEnd = .Cells.Find(what:="*", after:=.Range("A1"), LookAt:=xlPart, LookIn:=xlFormulas, searchorder:=xlByRows, searchdirection:=xlPrevious, MatchCase:=False).Row
columnEnd = .Cells.Find(what:="*", after:=.Range("A1"), LookAt:=xlPart, LookIn:=xlValues, searchorder:=xlByColumns, searchdirection:=xlPrevious, MatchCase:=False).Column
End With
This is just a portion of the program but the one I am most confused about. If anyone could help out I would really appreciate it. Also, if there is a better way to accomplish this task I'm all ears. The rest of my code is below for reference.
'Insert or Delete Space above the first used row
If rowStart < 4 Then
Do While rowStart < 4
Range("1:1").Select
Selection.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
ws.Select
With ActiveSheet
rowStart = .Cells.Find(what:="*", after:=.Range("A1"), LookIn:=xlValues, searchorder:=xlByRows, searchdirection:=xlNext).Row
End With
Loop
ElseIf rowStart > 4 Then
Do While rowStart > 4
Range("1:1").Select
Selection.Delete Shift:=xlUp
ws.Select
With ActiveSheet
rowStart = .Cells.Find(what:="*", after:=.Range("A1"), LookIn:=xlValues, searchorder:=xlByRows, searchdirection:=xlNext).Row
End With
Loop
End If
'I think I need to adjust the columnStart, rowEnd, and columnEnd values after inserting and deleting rows
ws.Select
printStart = ActiveSheet.Cells(1, columnStart).Address
printEnd = ActiveSheet.Cells(rowEnd, columnEnd).Address
'Format headers, footers, and set the print area
ActiveSheet.PageSetup.CenterHeaderPicture.Filename = _
"\\antilles\MyDocs\xxxx\My Documents\My Pictures\xxxx.png"
With ActiveSheet.PageSetup
.CenterHeader = "&G"
.LeftFooter = "&""Palatino Linotype,Regular""&F"
.CenterFooter = "&""Palatino Linotype,Regular""Prepared By: xxxx"
.RightFooter = "&""Palatino Linotype,Regular""&D"
.PrintArea = printStart & ":" & printEnd
End With
Next ws
Application.PrintCommunication = True
End Sub
I've done a lot of this and I recommend simple crude methods. Without coding a whole thing, but rather hinting...
dim iRow as integer
For iRow = 1 to ...
cells(iRow,65000).end(xlup).select
if activecell.row = 1 then
activecell.entirecolumn.delete
exit For
endif
next iRow
As much as possible force some structure on the sheets. Then go see
http://www.ozgrid.com/VBA/ExcelRanges.htm
When googling, include
ozgrid|Pearson|Tushar|"Mr. Excel"|Erlandsen|Peltier|dailydoseofexcel
in the search string.
Excel VBA offers a selection of techniques for finding the first or last used row or column but none work in every situation.
Some problems with your code:
If the worksheet contains something, Find returns a range. A range has a row so your statements will work. But if the worksheet is empty, Find returns Nothing. You must use Set Rng = .Cells.Find ... then test Rng to not be Nothing before accessing Rng.Row or Rng.Column. See the code I reference below if this is not clear.
Note the after in After:=.Range("A1"). Find does not examine .Range("A1") until it has searched every other cell and wraps back to the beginning. In any example in which the start point is .Range("A1") the search direction will be xlPrevious so it immediately wraps and starts searching from the bottom right cell. Try After:=.Cells(Rows.Count, Columns.Count) when the search direction is xlNext.
There was an earlier question that was similar to yours. I posted some code which showed a selection of techniques for finding the last row or column and the situations in which they fail. I suggest you visit that answer and try the code: https://stackoverflow.com/a/18220846/973283.
Good luck and happy VBA programming.

Copy last column with data on specified row to the next blank column

I have a spread sheet and I need to look for the last column that has data in it. Then I need to copy this column and copy it to the next blank column.
Is there a way to do this?
I've managed to do it with rows using:
lastrowSrc = Sheets("Overview").Range("B" & Rows.Count).End(xlUp).Row
However this puts B12 in the range, using columns.count simply puts in the number of the column, not the letter
To get the exact column in a worksheet, use this code.
Option Explicit
Sub Sample()
Dim ws As Worksheet
Dim LastCol As Long
Set ws = Sheets("Sheet1")
'~~> This check is required else .FIND will give you error on an empty sheet
If Application.WorksheetFunction.CountA(ws.Cells) = 0 Then
LastCol = 1
Else
LastCol = ws.Cells.Find(What:="*", _
After:=ws.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Column
End If
Debug.Print LastCol
End Sub
EDIT: This is courtesy #brettdj. You can also use the range object to find the last column
Option Explicit
Sub Sample()
Dim ws As Worksheet
Dim LastCol As Long
Dim rng As Range
Set ws = Sheets("Sheet1")
Set rng = ws.Cells.Find(What:="*", _
After:=ws.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False)
If rng Is Nothing Then
LastCol = 1
Else
LastCol = rng.Column
End If
Debug.Print LastCol
End Sub
To get the last column of a particular row, say row 1 use this
Debug.Print ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column
Where ws is your relevant worksheet.
Similarly for Row see this.
I found that some of the answers didn't work for my worksheet that had a few rows at the end that were shorter than the others in the worksheet. The code provided just gives the last column of the last row of the worksheet. Instead, I used a loop around code to find the last column in a row, using the Find example to get the last row in the workbook.
Sub Sample()
Dim ws As Worksheet
Dim CurrRow, RowLastCol, LastRow, LastCol As Long
Set ws = Sheets("Sheet1")
'~~> This check is required else .FIND will give you error on an empty sheet
If Application.WorksheetFunction.CountA(ws.Cells) = 0 Then
LastCol = 1
Else
LastCol = 0
LastRow = ws.Cells.Find(What:="*", _
After:=ws.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
' Loop through all the rows of the sheet saving off the highest column count
For CurrRow = 1 to LastRow
RowLastCol = ws.Cells(CurrRow, Columns.Count).End(xlToLeft).Column
If RowLastCol > LastCol Then
LastCol = RowLastCol
End If
Next CurrRow
End If
Debug.Print LastCol
End Sub