Using a subroutine's output as a variable in a separate subroutine - vba

Basically what I'm trying to do here is use this sub:
Sub SelectFirstBlankCell()
Dim sourceCol As Integer, rowCount As Integer, currentRow As Integer
Dim currentRowValue As String
sourceCol = ActiveCell.Column 'Uses ActiveCell.Column as reference now, but needs to fit into each Subroutine to select next available
rowCount = Cells(Rows.Count, sourceCol).End(xlUp).Row
'for every row, find the first blank cell and select it
For currentRow = 1 To rowCount
currentRowValue = Cells(currentRow, sourceCol).Value
If IsEmpty(currentRowValue) Or currentRowValue = "" Then
Cells(currentRow, sourceCol).Select
Exit For
End If
Next
End Sub
To find the next empty cell in a column to input the string from this sub into.
Set selRange = Selection
For i = 0 To ListBox1.ListCount - 1
If ListBox1.Selected(i) = True Then
If strApps = "" Then
strApps = ListBox1.List(i)
intAppCodeOffset = i
strAppCodeVal = Worksheets("TestSheet").Range("B31").Offset(i, 0).Value
Else
strApps = strApps & ", " & ListBox1.List(i)
intAppCodeOffset = i
strAppCodeVal = strAppCodeVal & ", " & Worksheets("TestSheet").Range("B31").Offset(i, 0).Value
End If
End If
Next
Set selRange = selRange.Offset(1, 0)
With selRange
selRange.Value = strAppCodeVal
End With
I've tried replacing selRage.Offset(1, 0) with SelectFirstBlankCell, but I get an object reference error every time. Any help would be greatly appreciated on this as I can't seem to find how to do it on here.

As mentioned in the comments above, try changing Sub to Function, like this:
Function SelectFirstBlankCell(sourceCol as Integer) as Range
(remove old sourceCol dim and assignment)
...
Set SelectFirstBlankCell = Cells(currentRow, sourceCol)
...
End Function
Then you can do your change:
Set selRange = SelectFirstBlankCell(ActiveCell.Column) 'Or whatever you think should be defined as the sourceCol
Your code should probably not select anything itself, unless that is the end result of your macro. Try to use the code to directly manipulate the cells instead.

Related

Add row when cell in table is not empty

This is the code that I have right now.
Do While IsEmpty(objTable.cell(intNoOfRow,2).Range.Text) = False
intNoOfRows = intNoOfRows + 1
Loop
Any help would be greatly appreciated.
IsEmpty tests to see if a Variant has a type of empty. It will always return False for a String. Test against vbNullString instead:
Do While objTable.cell(intNoOfRow,2).Range.Text = vbNullString
intNoOfRows = intNoOfRows + 1
Loop
We cannot use this code:
IsEmpty(objTable.cell(intNoOfRow,2).Range.Text) will always True, so the code will run into Infinite Loop. While Len(.Cell(intNoOfRows, 2).Range.Text) <>0 always return True too. We are not sure if this is by design or bug, but the new cell always contains character. Cell(intNoOfRow, 2).Range.Text = vbNullString doesn't work too.
Find a worked way on my side(InStr( [start], string, substring, [compare] ) ):
With objTable
Dim strCellText As String
strCellText = .Cell(intNoOfRow, 2).Range.Text
Do While InStr(1, strCellText, "", vbBinaryCompare) <> 1
MsgBox "OK"
Loop
End With
Some old try:
With objTable
For Each c In .Range.Rows
intNoOfRows = intNoOfRows + 1
Next
End With
Or
You can use the .Range.Rows.Count, but the following code still need to adjust
With objTable
Do While intNoOfRows < .Range.Rows.Count
intNoOfRows = intNoOfRows + 1
'MsgBox .Range.Rows.Count
'If intNoOfRows > .Range.Rows.Count Then
' Exit Do
'End If
Loop
End With
Try something based on:
Sub Demo()
Dim r As Long, i As Long
With ActiveDocument.Tables(1)
For r = 1 To .Rows.Count
With .Rows(r)
If Len(.Range.Text) = .Cells.Count * 2 + 2 Then i = i + 1
End With
Next
End With
MsgBox "There are " & i & " empty rows in the table"
End Sub
Similarly, to add a row before a non-empty row, you might use something like:
Sub Demo()
Dim r As Long, i As Long
With ActiveDocument.Tables(1)
For r = 1 To .Rows.Count
If Len(.Rows(r).Range.Text) > .Rows(r).Cells.Count * 2 + 2 Then
.Rows.Add .Rows(r)
End If
Next
End With
End Sub

Loop through excel rows and call VBA functions

I need to be able to loop through my rows (specifically, column B), and use the number in a certain cell in order to do specific functions using other cells in that row. For example, Rule #1 indicates that I need to find last modified date of the path in the cell next to the Rule #, but the task is different for each Rule.
I'm new to VBA and I've just been struggling with setting up a loop and passing variables to different subs, and would hugely appreciate any help. To be clear, I'm looking for syntax help with the loop and passing variables
Thank you!
Reference Images: The spreadsheet
The attempt at sketching out the code
Private Sub CommandButton1_Click()
Dim x As Integer
NumRows = Range("B2", Range("B2").End(xlDown)).Rows.Count
Range("B2").Select
For x = 1 To NumRows
If Range(RowCount, 1).Value = 1 Then
RuleOne (RowCount)
End If
Next
'Dim RowCount As Integer
'RowCount = 1
'Worksheets("Sheet2").Cells(1, 2) = Worksheets("Sheet1").UsedRange.Row.Count
'While RowCount < Worksheets("Sheet1").Rows
'If Worksheets("Sheet1").Cells(RowCount, 1).Value = 1 Then
'RuleOne (RowCount)
'End If
'Wend
End Sub
Sub RuleOne(i As Integer)
'use filedatetime and path from i cell
'Worksheets("Sheet2").Cells(1, 1) = FileDateTime(C, i)
Worksheets("Sheet2").Cells(1, 1) = "hello"
End Sub
Sub RuleTwo(i As Integer)
Worksheets("Sheet2").Cells(1, 1) = "hello"
End Sub
Try to change the Range(RowCount, 1).Value = 1 to Cells(x, 2).Value = 1.
The variable RowCount has not been initialised/set.
I assume this is what this variable is meant to be the number in column B
RowCount = Cells(x, "B").Value
I also noticed that the variable NumRows seemed to be one less than it should be (so if the last row was 1 it would skip it). So I used this instead:
NumRows = Cells(Rows.Count, "B").End(xlUp).Row
So try this code:
Sub CommandButton1_Click()
Dim x As Integer
NumRows = Cells(Rows.Count, "B").End(xlUp).Row
For x = 1 To NumRows
RowCount = Range("B" & x).Value
If RowCount = 1 Then
RuleOne (x)
End If
Next
'Dim RowCount As Integer
'RowCount = 1
'Worksheets("Sheet2").Cells(1, 2) = Worksheets("Sheet1").UsedRange.Row.Count
'While RowCount < Worksheets("Sheet1").Rows
'If Worksheets("Sheet1").Cells(RowCount, 1).Value = 1 Then
'RuleOne (RowCount)
'End If
'Wend
End Sub
Sub RuleOne(i As Integer)
'use filedatetime and path from i cell
'Worksheets("Sheet2").Cells(1, 1) = FileDateTime(C, i)
Worksheets("Sheet2").Cells(1, i) = "hello"
End Sub
Sub RuleTwo(i As Integer)
Worksheets("Sheet2").Cells(1, 1) = "hello"
End Sub

Excel VBA - list all VBA environmental variables

How can I get excel to list me all available environmental variables on my "temp" sheet? Below code doesnt return anything for me...
Sub ListEnvironVariables()
Dim strEnviron As String
Dim i As Long
For i = 1 To 255
strEnviron = Environ(i)
If LenB(strEnviron) = 0& Then Exit For
Debug.Print strEnviron
Next
End Sub
Thanks
few lines modified from your code as below.
Sub ListEnvironVariables()
Dim strEnviron As String
Dim i As Long
For i = 1 To 255
strEnviron = Environ(i)
If LenB(strEnviron) = 0& Then Exit For
With Worksheets("temp")
.Range("A" & Range("A" & Rows.Count).End(xlUp).Row + 1).Value = strEnviron
End With
Next
End Sub
Now I have changed the coding . This will list out all of the environment variables in your immediate window. If you can't see this, choose this menu option:
Sub ListEnvironmentVariables()
'each environment variable in turn
Dim EnvironmentVariable As String
'the number of each environment variable
Dim EnvironmentVariableIndex As Integer
Dim i As Long
'get first environment variables
EnvironmentVariableIndex = 1
EnvironmentVariable = Environ(EnvironmentVariableIndex)
'loop over all environment variables till there are no more
Do Until EnvironmentVariable = ""
'get next e.v. and print out its value
With Worksheets("temp")
.Cells(i, 1).Value = EnvironmentVariableIndex
.Cells(i, 2).Value = EnvironmentVariable
End With
'go on to next one
EnvironmentVariableIndex = EnvironmentVariableIndex + 1
i = i + 1
EnvironmentVariable = Environ(EnvironmentVariableIndex)
Loop
End Sub
Plz look into this also for further reference
http://www.wiseowl.co.uk/blog/s387/environment-variable-vba.htm

Transferring data from one workbook to another workbook daily into specific/empty cells

I am in the process of developing a macro that will Transfer Data from one workbook (enterdata) to another workbook (extractdata) while having a mass collection of formulas in the extractdata workbook. I need to have the data extracted into specific cells as data gets input day by day. This data needs to be compiled and I am having troubles with this portion.
I need the data extracted into specific cells because if I use the empty row functions I have formulas at the end of my rows and bottom of my columns therefore I am trying to have the data input into specific cells
I think I am on the right track but I continuously have Run-time error '1004': stating select method of range class failed.
Thanks in advance,
Anderson
'Next the transfers of the data from the daily quality activity to the specific worksheet of the unit charts'
'Accesories'
Set myData = Workbooks.Open("C:\database\Extractdata.xlsm")
Worksheets("ACC").Select
Dim sourceCol As Integer, rowCount As Integer, currentRow As Integer
Dim currentRowValue As String
sourceCol = 1 'column A has a value of 1
rowCount = Cells(Rows.Count, sourceCol).End(xlUp).Row
'for every row, find the first blank cell and select it
For currentRow = 3 To rowCount
currentRowValue = Cells(currentRow, sourceCol).Value
If IsEmpty(currentRowValue) Or currentRowValue = "" Then
Cells(currentRow, sourceCol).Select
End If
Next
With Worksheets("ACC").Range("A3")
.Offset(ColumnCount, 0) = currentDate
.Offset(ColumnCount, 1) = devicesStockedACC
.Offset(ColumnCount, 2) = qipAttemptsACC
.Offset(ColumnCount, 3) = qipncproductCountACC
.Offset(ColumnCount, 4) = totalqcncCountACC
.Offset(ColumnCount, 5) = devicencidCountACC
.Offset(ColumnCount, 6) = componentncidCountACC
End With
NEW CODE 3/13/14
Dim currentDate As String
Dim devicesStockedACC As String
Dim qipAttemptsACC As String
Dim qipncproductCountACC As String
Dim totalqcncCountACC As String
Dim devicencidCountACC As String
Dim componentncidCountACC As String
'Acessories'
Worksheets("tuesday").Select
currentDateACC = Range("A1")
Worksheets("tuesday").Select
devicesStockedACC = Range("C12")
Worksheets("tuesday").Select
qipAttemptsACC = Range("D12")
Worksheets("tuesday").Select
qipncproductCountACC = Range("E12")
Worksheets("tuesday").Select
totalqcncCountACC = Range("H12")
Worksheets("tuesday").Select
devicencidCountACC = Range("L12")
Worksheets("tuesday").Select
componentncidCountACC = Range("M12")
'Next the transfers of the data from the daily quality activity to the specific worksheet of the unit charts'
'Accesories'
Set myData = Workbooks.Open("C:\database\Extractdata.xlsm")
Worksheets("ACC").Select
Worksheets("ACC").Range("A3").Select
Application.Run "Selectfirstblankcell"
Sheets("ACC").Activate
With Worksheets("ACC").Range(ActiveCell)
.Offset(ColumnCount, 0) = currentDate
.Offset(ColumnCount, 1) = devicesStockedACC
.Offset(ColumnCount, 2) = qipAttemptsACC
.Offset(ColumnCount, 3) = qipncproductCountACC
.Offset(ColumnCount, 4) = totalqcncCountACC
.Offset(ColumnCount, 5) = devicencidCountACC
.Offset(ColumnCount, 6) = componentncidCountACC
.Offset(ColumnCount, 8) = currentDate
.Offset(ColumnCount, 15) = currentDate
End With
Application.Run "Selectfirstblankcell" =
Public Sub SelectFirstBlankCell()
Dim sourceCol As Integer, rowCount As Integer, currentRow As Integer
Dim currentRowValue As String
sourceCol = 1 'column F has a value of 6
rowCount = Cells(Rows.Count, sourceCol).End(xlUp).Row
'for every row, find the first blank cell and select it
For currentRow = 3 To rowCount
For currentCol = 1 To ColCount
currentCellValue = Cells(currentRow, currentCol).FormulaR1C1
If IsEmpty(currentCellValue) Or currentCellValue = "" Then
Cells(currentRow, currentCol).Select 'do something else than select maybe?
'put code here to handle the empty cell
Exit For 'this will exit the inner loop, so it will only process the first blank cell on each row
End If
Next
Next
End Sub
try using .formulaR1C1 instead of .value. your current code should run to the first empty cell in sourceCol
For currentRow = 3 To rowCount
currentRowValue = Cells(currentRow, sourceCol).formulaR1C1
If IsEmpty(currentRowValue) Or currentRowValue = "" Then
Cells(currentRow, sourceCol).Select
End If
Next
your above code (I changed from .value to .formular1C1) will loop through each row in sourceCol, and that if statement will be true if the current cell is empty. to loop through each cell (column) on each row you'd need another for loop. 1 for going down, 1 for going accross
For currentRow = 3 To rowCount
for currentCol = 1 to ColCount
currentCellValue = Cells(currentRow, currentCol).formulaR1C1
If IsEmpty(currentCellValue) Or currentCellValue = "" Then
Cells(currentRow, currentCol).Select 'do something else than select maybe?
'put code here to handle the empty cell
exit for 'this will exit the inner loop, so it will only process the first blank cell on each row
End If
next
Next
so that code will loop through each row, and the inner loop will loop over the columns in that row, and the if statement in the inner loop will be true when it encounters a blank cell, you can put whatever code in the if, and then it will exit the inner for loop, so as to only process the first blank column in each row. it wont exit the outer loop though, it'll move on to the next row.
Let me know how that works for you
edit
after the line: rowCount = Cells(Rows.Count, sourceCol).End(xlUp).Row
add this: colCount = Cells.find("*", [A1], , , xlByColumns, xlPrevious).column
when you use the debugger you can see the values of all your local variables. so when stuff like that happens where it just does nothing, make sure you check those get initialized.
sorry about not including that. now the inner loop should run.
also, in accessories, this: Worksheets("tuesday").Select only needs to be inlcluded once at the top of the accessories section. doing this: DevicesStockedAcc = Range("A1") doesnt deselect the worksheet so you dont need to select it again every time.
Also, I noticed when setting the accessories you're doing: currentDateACC = Range("A1") i also notcied the variable: currentDateACC you have as a string. so is this variable supposed to represent the value of a cell? or the cell itself? using just .range will get you a reference to the range, not the value in the cell. to get the value use: devicesStockedACC = Range("C12").value that will save the value in that cell as the string, and similarly, when doing your offsets use: .Offset(ColumnCount, 1).value = devicesStockedACC that should help some :)

Excel VBA Range(Cell).Value=sum 1004:Application-Defined Or Object-Defined

Function ChangeColVal(ByVal Rng As Range, ByVal ValueToChange As Integer)
Dim Cell1, Cell2 As String
Dim PosOfColon, TotalCell, Sum As Integer
PosOfColon = InStr(1, Rng.Address, ":")
Cell1 = Left(Rng.Address, PosOfColon - 1)
Cell2 = Right(Rng.Address, Len(Rng.Address) - PosOfColon)
If Left(Cell1, 2) = Left(Cell2, 2) Then
TotalCell = Rng.Count
For i = 0 To TotalCell
If IsNumeric(Range(Cell1).Offset(i, 0).Value) = False Then
GoTo 112:
End If
Cell2 = Range(Cell1).Offset(i, 0).Address
Sum = Range(Cell2).Cells.Value + ValueToChange
On Error GoTo 111
'Here getting error...
Range(Cell2).Value = Sum
GoTo 112
111:
MsgBox (Err.Number & ":" & Err.Description)
112:
Next i
Else
MsgBox ("Select Column only...")
End If
End Function
I wants to increase or decrease cell value of selected range.
I am getting error in line Range(Cell2).Value = Sum
Edit
thanx for reply, in line Range(Cell2).Value = Sum, Cell2 is pointing to cell address like $E$6.
If there is any option other than that pls let me know
ok Mihir. You cannot use a UDF (User Defined Function) to modify other cells then the one the formula is used in. However, there is a workaround it by calling your function from a sub. I will show you how to do it.
Open a new workbook and make your spreadsheet look like the picture below.
Fill in some random numbers in column A of Sheet1
Then open VBE and create a new module ( Project Explorer > Insert > Module ) and paste the code from below
Option Explicit
Sub ChangeColumnValue()
Dim rng As Range
Set rng = Selection
Dim inp As String
inp = InputBox("Value to change:")
Call ChangeColVal(rng, CLng(inp))
End Sub
Private Function ChangeColVal(ByRef rng As Range, ByVal ValueToChange As Long)
Dim Cell1, Cell2 As String
Dim PosOfColon, TotalCell, Sum As Long
PosOfColon = InStr(1, rng.Address, ":")
Cell1 = Left(rng.Address, PosOfColon - 1)
Cell2 = Right(rng.Address, Len(rng.Address) - PosOfColon)
If Left(Cell1, 2) = Left(Cell2, 2) Then
TotalCell = rng.Count
Dim i&
For i = 0 To TotalCell - 1
If Not IsNumeric(Range(Cell1).Offset(i, 0).Value) Then
GoTo 112:
End If
Cell2 = Range(Cell1).Offset(i, 0).Address
Sum = Range(Cell2).Cells.Value + ValueToChange
On Error GoTo 111
Range(Cell2).Value = Sum
GoTo 112
111:
MsgBox (Err.Number & ":" & Err.Description)
112:
Next i
Else
MsgBox ("Select Column only...")
End If
End Function
Then, go back to your spreadsheet and select your range with your mouse like this:
Ok, now hit ALT + F8 to View Macros and run the ChangeColumnValue macro.
You will be prompt for a Value to Change and all cells within selected range will be Increased/Decreased by that Value.
and your final result if you type 5 in the prompt box will look like this
Good luck!
finally here is the solution.
Sub ChangeRowValues()
Dim rng As Range
Dim R As Range
Dim ValueToChange As Long
Dim Cell1, Cell2 As String
Dim PosOfColon, TotalCell, Sums, i As Integer
Set rng = Selection
ValueToChange = Val(InputBox("Enter Number to Change:", "Enter Number...", 0))
PosOfColon = InStr(1, rng.Address, ":")
Cell1 = Left(rng.Address, PosOfColon - 1)
Cell2 = Right(rng.Address, Len(rng.Address) - PosOfColon)
If UCase(Left(Cell1, 1)) = UCase(Left(Cell2, 1)) Then
TotalCell = rng.Count
For i = 0 To TotalCell - 1
'To Chnage Values of Row....
Range(Cell1).Offset(0, i).Select
'To Chnage Values of Colum....
'Range(Cell1).Offset(i,0).Select
If IsNumeric(ActiveCell.Value) = True Then
ActiveCell.Value = Val(ActiveCell.Value) + ValueToChange
End If
Next i
Else
MsgBox ("Select Row only...")
End If
End Sub
range() function input is cell address, for example, range(a1:b2;g1:h4), you cannot input some result in it.