I'm having an issue with my For If statement. The scenario is that, I need the empty cells to be filled with a telephone number. I have made a code and it works but at some point it will stop in between. Sometimes all the way to the end of the last row or just skip a few cells and continue again. I'm really not sure about this weird issue, hopefully someone can give me an insight. I have also attached a snapshot of the results.
My code is as shown below:-
Dim pn As Range
Dim h As Integer, phone As Integer
lastrow = Range("A" & Rows.Count).End(xlUp).Row
Set pn = Range("AE2:AE" & lastrow)
h = 1
For phone = 1 To pn.Rows.Count
If pn.Cells(h) = "" Then
pn.Cells(h) = "03-33422828"
Else
h = h + 1
End If
Next
An alternative way to do this is to select all the used cells in that range, then fill all the blank ones with a value.
For example, if we have a workbook with data in column A and we want to fill the blank cells in that column with "---" we could do this:
On Error Resume Next
Range("A1:A" & ActiveSheet.UsedRange.Rows.Count). _
SpecialCells(xlCellTypeBlanks).Value = "---"
On Error GoTo 0
VBA will generate an error if there are no blank cells, so I've "handled" that by just ignoring any errors.
For you it would be more like:
On Error Resume Next
Range("AE1:AE" & ActiveSheet.UsedRange.Rows.Count). _
SpecialCells(xlCellTypeBlanks).Value = "03-33422828"
On Error GoTo 0
Related
I'm trying to fill 1299 cells in a row with the value 0530 using the following code:
Sub FillValues()
Dim X As Integer
For X = 2 To 1300
Worksheets("Table1").Range("B" & X).Value = "'0530"
Next X
End Sub
For some reason it doesn't work and I don't know why. The error is "Index beyond the valid range."
Please try (no loop):
Worksheets("Table1").Range("B2:B1300").Value = "'0530"
I want to produce a mini report of several items matching a key. In my loop I get the keys returned but can't fathom out how I can access the data that I need in the report that is held in other columns.
I put in some msgbox's to trap the data and an escape mechanism to get out of the loop. These I have commented out below as well as the data lines that don't work. "cbdata" is a workbook named range covering B5:T4019. The report is being compiled on a different sheet (activesheet). For some unknown reason on looping through without outputing any data "r" gets updated to some spurious numbers like 2421 (first loop) this appears to be linked somehow to the data in "cbdata". The first entry is actually in row 2388 so it doesn't really correlate to an indexed row in the range. However, I think first of all I need to find out what I can do to get the corresponding row returned for each of my passes. "ky" returns all the entries in columns(19) but I'm only interested in those that match "ledcdeyr" which in this instance is "2012017" that bit works returning all the entries matching in the loop.
Having got the key information agreeing, how might I relate this to the row number so that I can extract the other data from that row.
(cr is vbcrlf)(r should be the row number of the receiving report)
Any pointers would be greatly appreciated.
Code:
r = r + 1 ' row 38 when entering process
For Each ky In Range("cbdata").Columns(19).Cells
'ans = MsgBox(ky & cr & r, vbOKCancel)
'If ans = vbCancel Then Exit Sub
If ky = ledcdeyr Then
ans = MsgBox(ky & cr & r, vbOKCancel)
If ans = vbCancel Then Exit Sub
Cells(r, 2) = Range("cbdata").Cells(ky, 1)
'Cells(r, 3) = Range("cbdata").Columns(2).Cells
'Cells(r, 4) = Range("cbdata").Columns(3).Cells
'Cells(r, 5) = Range("cbdata").Columns(4).Cells
'Cells(r, 6) = Range("cbdata").Columns(5).Cells
ans = MsgBox(r, vbOKCancel + vbQuestion, title)
If ans = vbCancel Then Exit Sub
End If
r = r + 1
Next
I am not entirely sure I follow but the Range object during the loop is ky. The row for that cell be retrieved with .Row property
ky.Row
Somewhat random example with a conditional test:
Option Explicit
Public Sub Test()
Dim ky As Range, counter As Long
Dim loopRange As Range
Set loopRange = ThisWorkbook.Worksheets("Sheet1").Range("cbdata").Columns(19)
For Each ky In loopRange.Cells
counter = counter + 1
If ky = 1 Then
Debug.Print ky.Row, counter
Debug.Print loopRange(counter).Address
End If
Next
End Sub
I ran the undernoted slightly amended code on my project but it produced some spurious results.
I had already tried the ky.row but when it didn't give me the information, I just thought that it wasn't the answer.
Public Sub Test()
Dim ky As Range, counter As Long
Dim loopRange As Range
'Set loopRange = ThisWorkbook.Worksheets("Sheet1").Range("cbdata").Columns(19)
Set loopRange = Range("cbdata").Columns(19) ' workbook range name
For Each ky In loopRange.Cells
counter = counter + 1
'ans = MsgBox(counter & vbCrLf & ky & vbCrLf & ky.Row, vbOKCancel)
'If ans = vbCancel Then Exit Sub
If ky = 2012017 Then
Debug.Print ky.Row, counter
Debug.Print loopRange(counter).Address
End If
Next
End Sub
The Debug results from running the above code for the first 4 records were:
2388 2384
$CNK$5:$CNK$4091
2408 2404
$COE$5:$COE$4091
2444 2440
$CPO$5:$CPO$4091
2450 2446
$CPU$5:$CPU$4091
The numbers on the left produced by ky.row are correct. The numbers on the right relate somehow to the counter which here should be 1, 2, 3, 4. This is the same situation that occurred with my "r" and hence didn't produce the information where I expected to see it. Which caused me to think that ky.row was not working. Also my range "cbdata" is B5:T4091 The rows are correct but the "CNK" etc - I don't know where that has come from.
I thought I'd just feed back to you where I'm at and your reply certainly made me look further, as I seemed to be going round in circles.
If you have any idea how the counter would be acting so spuriously then perhaps you could let me know. Having used your code on its own the that clears up any issue with there not being a problem with any other part of my code. Thanks again.
Ok so the thing is, I'm writing this for an Excel Sheet, and the problem i've run into is the loop doesn't check to see if the destination cell is empty or not. So what i'm trying to do is check if the cell is empty if it is then do the existing paste. if it's not then keep looking till it finds the first empty box....can someone help with this?
Dim x, z
Set a = Sheets("Working")
Set b = Sheets("Peer Review")
Set c = Sheets("Waiting to Push")
Set d = Sheets("Completed")
x = 1
z = 2
Do Until IsEmpty(a.Range("I" & z))
If a.Range("I" & z) = "Peer" Then
x = x + 1
b.Rows(x).Value = a.Rows(z).Value
Else
If a.Range("I" & z) = "Waiting" Then
x = x + 1
c.Rows(x).Value = a.Rows(z).Value
End If
End If
z = z + 1
Loop
I'd recommend to rewrite the code as follows:
Option Explicit
Public Sub tmpSO()
Dim z As Long
Dim a As Worksheet, b As Worksheet, c As Worksheet, d As Worksheet
Set a = ThisWorkbook.Worksheets("Working")
Set b = ThisWorkbook.Worksheets("Peer Review")
Set c = ThisWorkbook.Worksheets("Waiting to Push")
Set d = ThisWorkbook.Worksheets("Completed")
z = 2
For z = a.Cells(a.Rows.Count, "I").End(xlUp).Row To 2 Step -1
If a.Cells(z, "I").Value2 <> vbNullString Then
Select Case UCase(a.Cells(z, "I").Value2)
Case "PEER"
b.Rows(b.Cells(b.Rows.Count, "I").End(xlUp).Row + 1).Value2 = a.Rows(z).Value2
a.Rows(z).Delete
Case "WAITING"
c.Rows(c.Cells(c.Rows.Count, "I").End(xlUp).Row + 1).Value2 = a.Rows(z).Value2
a.Rows(z).Delete
Case "COMPLETED"
d.Rows(d.Cells(d.Rows.Count, "I").End(xlUp).Row + 1).Value2 = a.Rows(z).Value2
a.Rows(z).Delete
Case Else
MsgBox "Unknown value " & a.Cells(z, "I").Value2 & " in row " & z & Chr(10) & "Skipping to next row..."
End Select
End If
Next z
End Sub
Changes:
Implement a for ... next instead of a loop is most of the time a better coding practice since a loop can potentially lead to an infinite loop and crash your Excel.
Using select case instead of multiple if clauses. This is not really much faster but simply better to read and understand.
I removed x because this would not always use the last row on each sheet. Instead x is incremented on each sheet and thus can lead to empty (in between) rows on all other sheets. Instead, the above code now checks column I for the last row on that sheet and then copies the row from sheet a over to the next available one.
The above code is now (no longer) case sensitive when checking for peer or Peer or pEEr in column I. I am guessing that this better suits your needs.
If an unknown value (other than peer, waiting, or completed) in column I is encountered then you get a message box telling you about it.
In accordance to your request (in the comments below) the above code now deletes any row which has been successfully copied over to another sheet. Yet, unrecognized values in column I cannot be copied over to any other sheet and (as such) stay on sheet a ("Working").
Note, that the above assumes that "empty" is defined as "there in nothing in the cell's formula. If you prefer you can also set it to "if the cell is showing no value" (instead). The difference is that if a cell contains a formula which results in "" then there is a formula in the cell but the value is currently (due to the formula) nothing.
Couldn't find a thread that would answer my question, os here I am. Please provide a link if there is one that I have not found.
Using Excel 2010
The comments should be sufficient to show what I'm trying to do.
I'm getting the Application-defined or Object-defined error (Runtime error 1004) I just can figure it out. Any help would be appreciated. Side note: I can get the loop to work when a formula like =if(A1=B1,"",3) If actually places the formula in the cell and show 3 in each cell when the condition is met. it just adding the Column,Row, I've tried & Range($, C) &, all sorts of combinations so, show me how much of a boob I am and help me with the SIMPLE fix that eludes me.
Thanks in advance.
Private Sub CommandButton1_Click()
Dim R, C As Integer
Dim Frmla1, Frmla2, Frmla3 As String
R = 4 'Initial Row #
C = 2 'Initial Column #
Frmla1 = "=IF('Log Sheet'!" '1st half of the formula
Frmla2 = "="""","""",'Log Sheet'!" '2nd half of the formula
Frmla3 = ")" 'Closing Parenthesis
' The Cells should have incremental Column,Row Identifiers.
' The following is what I want in each cell.
' The problem is trying to get the B4 and B5 into the formula.
' Formula "=IF('Log Sheet'!B4="","",'Log Sheet'!B4)
' Formula "=IF('Log Sheet'!B5="","",'Log Sheet'!B5)
For R = 4 To 301
ActiveSheet.Cells(R, C).Value = Frmla1 & R & C & Frmla2 & R & C & Frmla3
R = R + 2
Next R
End Sub
It looks like you should be using the R and C to reference a Range.Cells property that you can return a Range.Address property from.
For R = 4 To 301 Step 2
ActiveSheet.Cells(R, C).Formula = _
Frmla1 & Cells(R, C).Address(0, 0) & Frmla2 & Cells(R, C).Address(0, 0) & Frmla3
Next R
I've also removed your R = R + 2 and changed the Step of the For ... Next to increment by 2. You shouldn't self-increment a For ... Next inside the loop.
I changed the Range.Value property assignment to Range.Formula property. While your method often works, it wasn't correct and if the cells were formatted as Text, the formulas would come into the cells as text-that-looks=like-a-formula.
Your variable declarations should be more like the following.
Dim R As Long, C As Long
Dim Frmla1 As String, Frmla2 As String, Frmla3 As String
Each declaration should carry a variable type. Without it, they are declared as object/variant types,
this is my first time using the site, so forgive me for any inept explaining. I have a working macro to hide/unhide rows based on content of the rows, I just want it to be faster. Using a check box, when the box is checked, all rows with an "x" in column D get unhidden, those without an "x" get hidden. Same thing happens when it is unchecked, except it references column C, not D.
Right now, this code works. It's just a little slower than I'd like, since I'm sharing this with a bunch of people. Any ideas for how to speed it up? I'm pretty darn new to VB (the internet is astoundingly wise and a good teacher), but that doesn't matter. I already improved the code - before it selected each row, then referenced the column, and it was awful. Any ideas to speed it up (preferably without moving the screen) would be great.
Thanks so much folks,
DS
Sub NewLuxCheck()
Dim x As Integer
NumRows = Range("A42", "A398").Rows.Count
Range("A42").Select
If ActiveSheet.Shapes("checkbox2").OLEFormat.Object.Value = 1 Then
For x = 42 To NumRows + 41 Step 1
If Worksheets("Base").Range("D" & x).Value = "x" Then
Worksheets("Base").Range(x & ":" & x).EntireRow.Hidden = False
Else
Worksheets("Base").Range(x & ":" & x).EntireRow.Hidden = True
End If
Next
Else
For x = 42 To NumRows + 41 Step 1
If Worksheets("Base").Range("C" & x).Value = "x" Then
Worksheets("Base").Range(x & ":" & x).EntireRow.Hidden = False
Else
Worksheets("Base").Range(x & ":" & x).EntireRow.Hidden = True
End If
Next
End If
MsgBox ("Done")
End Sub
You could use array formula and let Excel to return array with row-numbers where 'x' value occures. It will be quicker but you'll have to reorganise your code and create separate functions etc.
Here example where array formula finds rows whre in column 'D' the cell has value 'x'. Then string of this row numbers is created in form of "A1,A5,A10" ...means 'x' was found in rows 1,5,10. And finally Range(rowsJoind).EntireRow.Hidden is used for all the rows to be hidden/un-hidden in one step.
For rows with value different then 'x' you'll have to use formula like '=IF({0}<>""x"", ROW({0}), -1)'.
Sub test()
Dim inputRange As Range
Dim lastRow As Long
Dim myFormula As String
Dim rowsJoined As String, i As Long
Dim result As Variant
With Worksheets("Base")
lastRow = .Range("D" & .Rows.Count).End(xlUp).Row
Set inputRange = .Columns("D").Resize(lastRow)
Application.ReferenceStyle = xlR1C1
myFormula = "=IF({0}=""x"", ROW({0}), -1)"
myFormula = VBA.Strings.Replace(myFormula, "{0}", inputRange.Address(ReferenceStyle:=xlR1C1))
result = Application.Evaluate(myFormula)
result = Application.Transpose(result)
Application.ReferenceStyle = xlA1
For i = LBound(result) To UBound(result)
If (result(i) > -1) Then
rowsJoined = rowsJoined & "A" & result(i) & IIf(i < UBound(result), ",", "")
End If
Next i
.Range(rowsJoined).EntireRow.Hidden = False
End With
End Sub