VBA for Excel 2007 and above - vba

I have written some VBA code that looks at a column, finds the next cell in that column which contains data, and sets the cells in between the two as a range. This was originally written for an Excel 2003 Workbook. And of course the same command does not work for a 2007 and above workbook. Can anyone help translate this for 2010 Excel VBA.
Here is the original Code:
Dim first As Integer
Dim Last As Integer
Dim i As Integer
Dim n As Integer
n = Worksheets("Sheet1").Range("A:A").Cells.SpecialCells(xlCellTypeConstants).Count - 2
Range("A3").Select
For i = 1 To n
first = (ActiveCell.Row + 1)
Selection.End(xlDown).Select
Last = (ActiveCell.Row - 1)
Range("J" & first & ":J" & Last).Select
Selection.Value = "=J$" & (first - 1)
Range("A" & Last + 1).Select
Next i
When I run it in Excel 2010. Instead of finding the next cell in Column A that contains data it just select the entire column.
Thanks in Advance.

Sub GoDownList()
Dim first As Integer
Dim Last As Integer
Dim i As Integer
Dim n As Integer
first = Range("A3").Row
Last = Range("A3").End(xlDown).Row
Range("J" & first & ":J" & Last).Value = "=J$" & (first - 1)
Do
first = Range("A" & Last).End(xlDown).Row
Last = Range("A" & first).End(xlDown).Row
Range("J" & first & ":J" & Last).Value = "=J$" & (first - 1)
If Range("A" & Last).End(xlDown).Row > 1000000 Then
Exit Do
End If
Loop
End Sub
I think your code doesnt work because you used Selection.Value instead of Selection.Formula.

Related

I am getting this error message. Run Time error '1004' Method 'Range' of object'_Global' Failed

I am trying to copy text values only from column H and move them to E. I want to automate it so that everytime a text value comes to H from sheet1, it directly goes to E instead of H. Leaving H empty in that cell.
Sheets("102Tk").Select
Dim row As Long
For row = 17 To 1000
' Check if "textvalue" appears in the value anywhere.
If WorksheetFunction.IsText(Range("H" & i)) Then
' Copy the value and then blank the source.
Range("E" & i).value = Range("H" & i).value
Range("H" & i).value = ""
End If
Next
End Sub
Should i be row?
Option Explicit
Sub n()
Sheets("102Tk").Select
Dim row As Long
For row = 17 To 1000
' Check if "save" appears in the value anywhere.
If Not IsNumeric(Range("H" & row)) Then
' Copy the value and then blank the source.
Range("E" & row).Value = Range("H" & row).Value
Range("H" & row).Value = ""
End If
Next
End Sub
Which avoiding using row as a variable name and a few other tidies could be:
Option Explicit
Public Sub SetValues()
Dim currentRow As Long
With ThisWorkbook.Worksheets("102Tk") 'taking note of the comments and using worksheet collection to avoid Chart sheets
For currentRow = 17 To 1000
' Check if "save" appears in the value anywhere.
If Not IsNumeric(.Range("H" & currentRow)) Then
' Copy the value and then blank the source.
.Range("E" & currentRow) = .Range("H" & currentRow)
.Range("H" & currentRow) = vbNullString
End If
Next currentRow
End With
End Sub

VBA - Loading master workbook using another workbook

I got these 2 tables, 1 is a datatable, the 2nd is a instruction table.
everyday i will update the instruction table, and run the macro, which will update the datatable accordingly based on ID.
It is currently really simple. If datatable ID (Col A) matches instructiontable ID (Col J) then the corresponding data Col B-F will update according to instructiontable.
Datatable
Col A= ID
Col B-G = Different names
The instruction table is:
Col I is add (change to Y) or delete (change to N) Col K i
Col J is ID
COl K indicates which name (Header of Col B-G) to update.
Sub updatedatatable()
On Error Resume Next
Dim instructionlastrow, findtablecolumn, findtablerow As Long
Dim findid As Integer
instructionlastrow = Range("I" & Rows.Count).End(xlUp).Row
For i = 2 To instructionlastrow
findid = 0
If Range("I" & i).Value = "Add" And Range("A:A").Find(Range("J" & i).Value).Row = 0 Then
Range("A" & Range("A" & Rows.Count).End(xlUp).Row + 1).Value = Range("J" & i).Value
findtablecolumn = Rows(1).Find(Range("K" & i)).Column
findtablerow = Range("A:A").Find(Range("J" & i)).Row
Cells(findtablerow, findtablecolumn).Value = "Y"
ElseIf Range("I" & i).Value = "Add" And Range("A:A").Find(Range("J" & i).Value).Row <> 0 Then
findtablerow = Range("A:A").Find(Range("J" & i)).Row
findtablecolumn = Rows(1).Find(Range("K" & i)).Column
Cells(findtablerow, findtablecolumn).Value = "Y"
ElseIf Range("I" & i).Value = "Remove" And Range("A:A").Find(Range("J" & i).Value).Row <> 0 Then
findtablerow = Range("A:A").Find(Range("J" & i)).Row
findtablecolumn = Rows(1).Find(Range("K" & i)).Column
Cells(findtablerow, findtablecolumn).Value = "N"
End If
Next i
End Sub
i was wandering if anyone can teach me so that the Instruction table can be loaded from a different workbook.
Thanks
I'm not sure excactly what the relation of the two tables are supposed to be according to your description, but I understand as this; you currently have them in the same workbook (in the same worksheet?) but want to have them in different workbooks.
To access a workbook from another workbook in vba you can use the Workbooks.Open method
https://msdn.microsoft.com/en-us/library/office/ff194819.aspx
I can also recommend some code examples from Ron de Bruin
http://www.rondebruin.nl/win/section3.htm
Since you haven't made any coding attempts to access separate workbooks I'm not 100% what you want to do, but please have a look at the links, make an attempt at a solution and get back if you get stuck again.

Dyanmic VBA code for changing the vba when a sheet name is changed

I have a vba code which specifies particular sheet names to look at for example sheet 2,
But what if, someone forgot to change the sheet name to sheet2, can I add a piece of dynamic code to automatically change the vba code for which ever the sheet name is called? for example the second sheet in from the left.
Code Module 1:
Sub Calculation()
Range("P2:P800").Select
Application.CutCopyMode = False
Selection.ClearContents
Dim dict1 As Object
Dim c1 As Variant, k As Variant
Dim currWS As Worksheet
Dim i As Double, lastRow As Double, tot As Double
Dim number1 As Double, number2 As Double, firstRow As Double
Set dict1 = CreateObject("Scripting.Dictionary")
Set currWS = ThisWorkbook.Sheets("Trade data")
'get last row withh data in Column A
lastRow = currWS.Cells(Rows.Count, "M").End(xlUp).Row
'put unique numbers in Column A in dict1
c1 = Range("M2:V" & lastRow)
For i = 1 To UBound(c1, 1)
If c1(i, 1) <> "" Then
'make combination with first 4 characters
dict1(Left(c1(i, 1), 4) & "," & Left(c1(i, 8), 4) & "," & Left(c1(i,
6), 10) & "," & Left(c1(i, 10), 7)) = 1
End If
Next i
'loop through all the numbers in column A
For Each k In dict1.keys
number1 = Split(k, ",")(0)
number2 = Split(k, ",")(1)
tot = 0
firstRow = 0
For i = 2 To lastRow
If k = Left(currWS.Range("M" & i).Value, 4) & "," &
Left(currWS.Range("T" & i).Value, 4) & "," & currWS.Range("R" &
i).Value & "," & (currWS.Range("O" & i).Value) Then
If firstRow = 0 Then
firstRow = i
End If
tot = tot + currWS.Range("W" & i).Value
End If
Next i
currWS.Range("P" & firstRow) = tot
Next k
Call Consolidate
Call SingleTradeMove
End Sub
Module 2 code:
Sub SingleTradeMove()
Dim wsTD As Worksheet
Set wsTD = Worksheets("Trade data")
Sheets("UnMatching").Range("A2:AK600").ClearContents
With wsTD
lastRow = .Range("A" & .Rows.Count).End(xlUp).Row
For i = 2 To lastRow
If Left(.Cells(i, "M"), 4) <> Left(.Cells(i, "T"), 4) _
Or .Cells(i, "O") <> .Cells(i, "V") _
Or .Cells(i, "R") <> .Cells(i, "Y") Then
.Cells(i, "J").EntireRow.Copy _
Destination:=Sheets("UnMatching").Range("A" & Rows.Count).End(xlUp).Offset(1)
End If
Next i
End With
End Sub
Building off ian0411's answer since I can not comment yet. You can also change this name to short hand. I always change mine to CN and then an abbreviation or something short enough its not a hassle to type out. In the example the sheet name in excel is BlueMoon. So I used CNBM in VBA. This gives a reference to the sheet, and the sheet name on excel's side can be changed without effecting your code. To change the name, click the sheet you want to name in the properties box. Then below that alter the (Name) option.
Say you have a sheet named "Work data" and you programmed as Sheets("Work data"). To make this dynamic, you can use the name before the parenthese that when you launch your Visual Basic editor.
For example, you have this code:
Sheets("Work data").Select
Now you can change to this:
Sheet1.Select
And this way, no matter how users changed the sheet name, it will always work. BUT please remember, the Sheet1 can be also changed but that can only be done inside Visual Basic editor properties. You can password protected the VBA so no one can accidentally alter it.

Excel - VBA : loop as long as content of a cell equals specific value

I am trying to modify my code to allow more factors to be taken into account when running a loop. Here is what I have so far, it's a loop running for i = 2 to 605 (because between 2 and 605, my G column's value is always the same "Makati City").
For this loop, I have some actions defined and it's working well. Here is the relevant code showing what my loop is doing :
For i = 2 To lRowBldg
Range("B" & i).Activate
'try to find a match btwn active cell and one of the elements from parsed address
For Each cell In elementsListRange.Cells
If Match(ActiveCell.Value, cell.Value) Then
Range("K" & i).Value = Range("K" & i).Value + 13
Else
Range("K" & i).Value = Range("K" & i).Value + 0
End If
If Match(ActiveCell.Offset(0, 4).Value, cell.Value) Then
Range("K" & i).Value = Range("K" & i).Value + 8
Else
Range("K" & i).Value = Range("K" & i).Value + 0
End If
Next
Next i
But as I plan to make some modifications to this file, I need to rethink my code. So far, I had only this file for one city so basically I could loop from the first to the last value and it was ok. Now, I plan to add more cities : for example, from 2 to 605 (Makati City), from 606 to 900 (blabla City), from 901 to ... and so on.
What I try to do is something like this :
"Loop for as long as the value of the cell in G column is equal to XXXXX (could be Makati City, could be blabla City, whatever)"
And if I mention Makati City, it will loop for i = 2 to 605, if it's blabla City, then it will loop for i = 606 to 900, and so on.
Do you have any idea about how to do this in such a way that wouldn't be too resource consuming as my file could end up being very long ?
Thanks so much in advance !
Use a while?
Here is some Idea....
Sub Test()
dim rng as range
rng = worksheet.find
While rng.Value2 LIKE "Makhati City"
'your logic here
rng.offset(row+1,col+0 or like this)
Wend
End Sub
you could try this, using columns L & N, and avoiding a loop entirely:
put all the code in a standard module then modify the code in setColumnKValues to search for differenct cioy names in column G.
ASSUMPTIONS:
That the differencet cities will be grouped together
that you can use a couple of extra columns (in this case L & N) as intermediates
that you will call setFormulasColumnK in the order of the cities on the sheet
that, based on the code in your question, you want to add a number to column K if the condition is met.
How does it work:
first, in column N we put marker values showing where the city changes
then, in column L we put in a formula, if it matches the city passed in, then L=K+13
finally, we copy paste the new values in column K, and clear columns L & N
Private oLastRange As Range
Private iFirstCell As Integer
Private iLastCell As Integer
Private lLastRow As Long
Sub setFormulasColumnK(ByVal sCity As String)
Dim sFormula As String
Dim oRange As Range
lLastRow = Cells(Rows.Count, Range("G1").Column).End(xlUp).Row
Range("N4:N" & lLastRow).Formula = "=IF(G4<>G5,NA(),"""")"
If Not Range("G:G").Find(sCity) Is Nothing Then
iFirstCell = Range("G:G").Find(sCity).Row
Else
Exit Sub
End If
Set oRange = Range("N" & iFirstCell)
iLastCell = Range("N" & iFirstCell & ":N" & lLastRow).Find("#N/A", oRange).Row
Range("L" & iFirstCell & ":L" & iLastCell).Formula = "=IF(TRIM(G:G)=""" & sCity & """,K:K+13,0)"
Set oLastRange = Range("L" & iLastCell)
End Sub
Sub setColumnKValues()
Set oLastRange = Nothing
Call setFormulasColumnK("Makati City")
'MsgBox oLastRange.Address
Call setFormulasColumnK("London")
'MsgBox oLastRange.Address
Call setFormulasColumnK("Birmingham")
'MsgBox oLastRange.Address
Call setFormulasColumnK("Moscow")
'MsgBox oLastRange.Address
Call setFormulasColumnK("Luxembourg")
'MsgBox oLastRange.Address
Call setFormulasColumnK("Paris")
'MsgBox oLastRange.Address
Range("L4" & ":L" & lLastRow).Copy
Range("K4" & ":K" & lLastRow).PasteSpecial xlPasteValues
Range("N4:N" & lLastRow).Clear
Range("L4" & ":L" & lLastRow).Clear
End Sub

Specifying cell addresses in Excel formula arguments using VBA

I have A column and B column, They compare their previous values And Iam comparing it with the following formulae
=IF((OR(AND(A2=A1,B2=B1),K2=0),0,1) it puts the 0 or 1 on the coresponding Q column
so when it goes to the 5th cell then it becames
=IF((OR(AND(A5=A4,B5=B4),K5=0),0,1)
But im trying to apply it in my VBA code like these
For numm = 2 To lastRow
Sheet1.Cells(numm, "Q").Value = ="IF(OR(AND(sheet1.cells(numm,""A"").value=sheet1.cells(numm-1,""A"")simlar way becolumn),sheet1.cells(numm,""k"").value=0),1,0)"
Next numm
But Im unable to peform the action it says 1004 error and object error
How do i use cells(numm,"A") in my VBA formulae or atleast any other way to put my formula and make it work
The reference to the looping numm within your formula needs to be out of the string.
Maybe you can set in VBA the cell formula itself...
For numm = 2 To lastRow
Sheet1.Cells("Q" & numm).Formula = _
"=IF((OR(AND(A" & numm & "=A" & numm - 1 & ",B" & numm & _
"=B" & numm - 1 & "),K" & numm & "=0),0,1)"
Next numm
Personally, I'd do the whole statement within VBA (ifs, ors, ands) and just drop the value back to Excel. Using Excel formulas makes the code harder to read.
Are you looking for something like:
Public Sub test()
Dim Sheet1 As Excel.Worksheet
Set Sheet1 = ActiveSheet
Dim numm As Integer, lastrow As Integer
lastrow = 5
For numm = 2 To lastrow
Sheet1.Cells(numm, "Q").Value = "=IF(OR(AND(" & Sheet1.Cells(numm, "A").Address & "=" & Sheet1.Cells(numm - 1, "A").Address & "," & Sheet1.Cells(numm, "B").Address & "=" & Sheet1.Cells(numm - 1, "B").Address & ")," & Sheet1.Cells(numm, "k").Address & "=0),1,0)"
Next numm
End Sub
Sheet1 can't be referred to inside the value of the cell, it only exists in the vba function you're creating, so instead you can append the strings together, and just get the cell addresses out to match the sort of function you were creating earlier.