I have this Excel spreadsheet that I am trying to create a working macro (in VBA) that when a cell containing a date (dates in order by a row in the B column), and this cell is in a specific color, and this cell is active, and the user clicks on a button, the macro searches for all the dates equal to the date in the active cell and to its color. Then in column H, the number value of the respective rows to the found dates are added up and stored into a variable called totalValue Then afterwards, the date, description, and the totalValue are copied over to another sheet and pasted in the next available predefined row.
I know that the color sort works for one color, I am using more than one color layout. The problem is when I run the macro, it seems to add all the number values in Column H within the date and it does not filter out the colors. But, when I take out block of code for "if color equals this, then do math" in lines 52 & 53 (ElseIf rFound.Style.Name = "Shipping" Then totalValue = totalValue + rFound.Offset(0, 6).Value ' THIS VALUE GOES TO Column E "Summary Sheet" ) then the color value for the code above that in lines 49 & 50 works (ElseIf rFound.Style.Name = "Office" Then totalValue = totalValue + rFound.Offset(0, 6).Value ' THIS VALUE GOES TO Column E "Summary Sheet"), but not the code above that lines 46 & 47 unless I take out the code in lines 49 & 50 as well, otherwise it would still add all the values in Column E.
What am I doing wrong? How can I fix it so that it can find the dates in a set color and be able to have several set colors available for use without this addition problem?
The code in question starts at 'BEGINNING OF HELP SEGMENT and ends at 'END OF HELP SEGMENT. The code above, between 'BEGINNING of Search function for HELP SEGMENT and 'ENG of Search function for HELP SEGMENT is the gathering of search parameters.
Here is my code:
Sub Copy_and_Move_Jul()
'
' Copy_and_Move From July Payable Ledger to Jul Summary Macro
'
'BEGINNING of Search function for HELP SEGMENT
'********************************************
'Declare Var
Const AllUsedCellsColumnB = False
Dim rFound As Range, SearchRange As Range
Dim cellValue As Variant, totalValue As Variant
' Get the H value of active row and set it to totalValue
cellValue = Range("H" & ActiveCell.Row)
totalValue = cellValue
' GET & SEARCH FOR COLOR AND DATE OF ACTIVE CELL, AND GET THE VALUES IN COLUMN H AND RETURN VALUE TO "totalValue"
' set search range
Set SearchRange = Range("B7:B56")
' If there is no search range, show Msg
If Intersect(SearchRange, ActiveCell) Is Nothing Then
SearchRange.Select
MsgBox "You must select a cell in the date column before continuing", vbInformation, "Action Cancelled"
Exit Sub
End If
' Get search criteria & set it to rFound
Set rFound = SearchRange.Find(What:=ActiveCell.Value, _
After:=ActiveCell, _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
SearchFormat:=False)
'********************************************
ENG of Search function for HELP SEGMENT
' BEGINNING OF HELP SEGMENT
'********************************************************************************************************************
' If rFound is not Nothing, then do math. If rFound is Nothing, then findnext
If Not rFound Is Nothing Then
Do
If rFound.Style.Name = "Marketing" Then
totalValue = totalValue + rFound.Offset(0, 6).Value ' THIS VALUE GOES TO Column E "Summary Sheet"
ElseIf rFound.Style.Name = "Inventory" Then
totalValue = totalValue + rFound.Offset(0, 6).Value ' THIS VALUE GOES TO Column E "Summary Sheet"
ElseIf rFound.Style.Name = "Office" Then
totalValue = totalValue + rFound.Offset(0, 6).Value ' THIS VALUE GOES TO Column E "Summary Sheet"
ElseIf rFound.Style.Name = "Shipping" Then
totalValue = totalValue + rFound.Offset(0, 6).Value ' THIS VALUE GOES TO Column E "Summary Sheet"
End If
Set rFound = SearchRange.FindNext(rFound)
' Loop till all matching cells are found
Loop While Not rFound Is Nothing And rFound.Address <> ActiveCell.Address
End If ' End of the Color & Date search
'********************************************************************************************************************
' END OF HELP SEGMENT
'Select & copy Columns B - I of Row of Active Cell
Range("B" & ActiveCell.Row & ":G" & ActiveCell.Row).Select
Selection.Copy
'Go to "Summary" Sheet & Paste data in next available empty Row
Sheets("Summary").Select
Range("B56").End(xlUp).Offset(1, 0).Select
ActiveSheet.Paste
'Select Column D & delete unneeded Qty # and input a "y" for "Expsense"
Range("D" & ActiveCell.Row).Select
Application.CutCopyMode = False
ActiveCell.FormulaR1C1 = "y"
'Set Value of Column H
Range("E" & ActiveCell.Row) = totalValue
'Goto Column C, Check Cell Style and input where supplies came from
Range("C" & ActiveCell.Row).Select
If Worksheets("Summary").Range("C" & ActiveCell.Row).Style.Name = "Marketing" Then
ActiveCell.FormulaR1C1 = "Marketing Supplies"
ElseIf Worksheets("Summary").Range("C" & ActiveCell.Row).Style.Name = "Inventory" Then
ActiveCell.FormulaR1C1 = "Inventory Supplies"
ElseIf Worksheets("Summary").Range("C" & ActiveCell.Row).Style.Name = "Office" Then
ActiveCell.FormulaR1C1 = "Office Supplies"
ElseIf Worksheets("Summary").Range("C" & ActiveCell.Row).Style.Name = "Shipping" Then
ActiveCell.FormulaR1C1 = "Shipping Supplies"
End If
End Sub
Here is a picture, before taking out the code in lines 52 & 53, I hope this helps with my explanation as to what is happening:
Here is a picture, after taking out the code in lines 52 & 53, this is what it's supposed to do:
Much appreciation in advance!
Start by checking if all the style names in the search range have the expected values:
Sub styleNames()
Dim cl As Range, SearchRange As Range
Set SearchRange = Range("B7:B56")
For Each cl In SearchRange
If cl.Value <> vbNullString Then _
Debug.Print " row: " & cl.Row & " style name: " & cl.Style.name
Next cl
End Sub
If they do, then you know for sure it's your code which is the problem. Try rewriting it in a simpler and less convoluted way by introducing conditional statements in the for each loop instead.
Related
I have in my code variable named MyCol that gets the number of the column by month that was selected in a userform. for example October is in column U and November is in column V. I have a formula that I recorded and the month that was chosen is part of it but it is a problem because RC format is with specific reference and my variable is an integer.
I want that the formula will be dynamic.
This is the formula (column U means month that was chosen):
=IFNA(IF(VLOOKUP(AA2,sheet1!F:F,1,0)=AA2,U2,0),0)
That is the relavant part of the code:
Dim MonthName As String
Dim myCol As Integer
MonthName = ListMonth.Value
With MainWB.Worksheets("sheet2")
.Activate
.Range("L1:W1").Find(MonthName, , xlValues, xlWhole).Activate
End With
ActiveCell.Select
myCol = Selection.Column
Range("AB2").Select
ActiveCell.FormulaR1C1 = _
"=IFNA(IF(VLOOKUP(RC[-1],sheet1!C[-22],1,0)=RC[-1],RC[" & myCol & "],0),0)"
Range("AB2").AutoFill Destination:=Range("AB2:AB" & MLR), Type:=xlFillDefault
Replace your :
Range("AB2").Select
ActiveCell.FormulaR1C1 = _
"=IFNA(IF(VLOOKUP(RC[-1],sheet1!C[-22],1,0)=RC[-1],RC[" & myCol & "],0),0)"
With:
Range("AB2").FormulaR1C1 = _
"=IFNA(IF(VLOOKUP(RC[-1],sheet1!C[-22],1,0)=RC[-1],RC[-" & Range("AB2").Column - myCol & "],0),0)"
However, if you want to make your code run faster, and also avoid all the unecessary Activate, ActiveCell, Select, try the code below:
Dim FindRng As Range
MonthName = ListMonth.Value
With MainWB.Worksheets("sheet2")
Set FindRng = .Range("L1:W1").Find(MonthName, , xlValues, xlWhole)
End With
If Not FindRng Is Nothing Then
myCol = FindRng.Column
Else ' find was not successful finding the month name
MsgBox "Unable to find " & MonthName, vbCritical
Exit Sub
End If
Range("AB2").FormulaR1C1 = _
"=IFNA(IF(VLOOKUP(RC[-1],sheet1!C[-22],1,0)=RC[-1],RC[-" & Range("AB2").Column - myCol & "],0),0)"
I want to use a VBA Function to insert a formulas into cells based on two conditions.
The conditions are (1) there has to be something in the Description (Column D on my spreadsheet) and (2) the cell I'm pasting the code into has to be blank.
The best way I can see of doing this is with a loop, but I can't figure out how to update the references in my formulas to take account of the new position.
The code below works, but it does not check to see if the cells are empty first.
Range("B8").Formula = "=IF(D8="""","""",IF(ISERROR(VLOOKUP(Trim(D8),Sheet3!$B$8:$M$7500,2,FALSE)),"""",VLOOKUP(Trim(D8),Sheet3!$B$8:$M$7500,2,FALSE)))"
Range("B8").Select
Selection.AutoFill Destination:=Range("B8:B" & Total), Type:=x1filldefault
'Adds the above formula into the range B8 to B(the last cell in use)
Range("C8").Formula = "=IF(D8="""","""",IF(ISERROR(VLOOKUP(Trim(D8),Sheet3!$B$8:$M$7500,3,FALSE)),"""",VLOOKUP(Trim(D8),Sheet3!$B$8:$M$7500,3,FALSE)))"
Range("C8").Select
Selection.AutoFill Destination:=Range("C8:C" & Total), Type:=x1filldefault
'Adds the above formula into the range C8 to C(the last cell in use)
Range("E8").Formula = "=IF(D8="""","""",IF(ISERROR(VLOOKUP(Trim(D8),Sheet3!$B$8:$M$7500,4,FALSE)),"""",VLOOKUP(Trim(D8),Sheet3!$B$8:$M$7500,4,FALSE)))"
Range("E8").Select
Selection.AutoFill Destination:=Range("E8:E" & Total), Type:=x1filldefault
'Adds the above formula into the range E8 to E(the last cell in use)
Range("J8").Formula = "=IF(D8="""","""",IF(ISERROR(VLOOKUP(Trim(D8),Sheet3!$B$8:$M$7500,9,FALSE)),"""",VLOOKUP(Trim(D8),Sheet3!$B$8:$M$7500,9,FALSE)))"
Range("J8").Select
Selection.AutoFill Destination:=Range("J8:J" & Total), Type:=x1filldefault
'Adds the above formula into the range J8 to J(the last cell in use)
Range("A8").Formula = "=If(B8="""","""",Row(A8))"
Range("A8").Select
Untested, but this should do what you want.
In a loop:
For i = 8 to Total
If cells(i, 4) <> "" Then
AddFormulaIfNotBlank cells(i, 2), _
"=IF(D<r>="""","""",IF(ISERROR(VLOOKUP(Trim(D<r>),Sheet3!$B$8:$M$7500,2,FALSE))" _
& ","""",VLOOKUP(Trim(D<r>),Sheet3!$B$8:$M$7500,2,FALSE)))"
'add rest of formulas here....
Next i
Next i
Helper Sub: populate only empty cells, and adjust the formula for the current row
Sub AddFormulaIfNotBlank(c As Range, f As String)
If Len(c.value)=0 Then
c.formula = Replace(f, "<r>", c.Row)
End If
End sub
I've tested this briefly. it assumes that the currently selected cell is at the top of the column you want to work down through before you start the procedure. Also there isn't any error handling
Sub CopyFormulas()
Dim xlRange As Range
Dim xlCell As Range
Dim xlAddress As String
xlAddress = ActiveCell.Address & ":$" & Mid(ActiveCell.Address, 2, InStr(1, ActiveCell.Address, "$")) & Mid(Cells.SpecialCells(xlCellTypeLastCell).Address, InStrRev(Cells.SpecialCells(xlCellTypeLastCell).Address, "$"), Len(Cells.SpecialCells(xlCellTypeLastCell).Address))
Set xlRange = Range(ActiveCell, xlAddress)
For Each xlCell In xlRange
xlAddress = "D" & Mid(xlCell.Address, InStrRev(xlCell.Address, "$"), Len(xlCell.Address))
If xlCell.Value = "" And Range(xlAddress).Value <> "" Then
xlCell.Value = "=IF(D8="""","""",IF(ISERROR(VLOOKUP(Trim(D8),Sheet3!$B$8:$M$7500,2,FALSE)),"""",VLOOKUP(Trim(D8),Sheet3!$B$8:$M$7500,2,FALSE)))"
End If
Next xlCell
End Sub
I'm sure there's an obvious answer here, but I'm stuck. This part in particular is throwing 424: Object Required. The really odd part, to me, is that it does successfully append 0s to the column, but then halts, and doesn't continue.
If cellLen < 9 Then
Set C.Value = 0 & C.Value
End If
The rest of the code is below for clarity. In case it's not clear, this is the intended code flow:
Grabs named fields
Copies those columns to a new sheet
Renames them and deletes the original sheet
Creates some new sheets for use with a different script
Searches for missing leading 0s in a specific column
Adds them back in (this is the part the breaks)
Deletes rows where that specific column's cell value is 0
Pulls that cleaned-up column out to a new file and saves it
Sub Cleanup_Mapwise_Import()
Dim targetCols As Variant
Dim replColNames As Variant
Dim index As Integer
Dim found As Range
Dim counter As Integer
Dim headerIndex As Integer
Dim question As Integer
Dim rowCount As Variant
Dim colNum As Variant
Dim colLetter As Variant
Dim C As Range
Dim cellLen As Integer
' Add or remove fields to be copied here
targetCols = Array("gs_account_number", "gs_meter_number", "gs_amr_identification", _
"gs_amr_phase", "gs_city", "Name", "Phase", _
"gs_rate_schedule", "gs_service_address", _
"gs_service_map_location", "gs_service_number")
' Put the same fields from above in the desired order here, with the desired name
replColNames = Array("Acct #", "Meter #", "AMR ID", "AMR Phase", "City", _
"Name", "Phase", "Rate", "Address", "Srv Map Loc", "Srv Num")
counter = 1
ActiveSheet.Range("A1").Select
' This counts the number of columns in the source array and sets the index to that value
For index = LBound(targetCols) To UBound(targetCols)
Set found = Rows("1:1").Find(targetCols(index), LookIn:=xlValues, LookAt:=xlWhole, _
SearchOrder:=xlByColumns, SearchDirection:=xlNext, MatchCase:=False)
' This is basically an insertion sort, and ends up with the columns in A:K
If Not found Is Nothing Then
If found.Column <> counter Then
found.EntireColumn.Cut
Columns(counter).Insert shift:=xlToRight
Application.CutCopyMode = False
End If
counter = counter + 1
End If
Next index
' There is a more dynamic way of doing this, using index
' As it is, replace A:K with the range of actual data
' PROTIP: targetCols is 1-indexed, and has 11 entries -->
' A:K encompasses that entire array -->
' Add/subtract 1 for each entry you add/remove
Range("A:K").Cut
Set TargetSheet = Sheets.Add(After:=Sheets(Sheets.Count))
TargetSheet.Name = "Contributors"
Range("A:K").Insert
question = MsgBox("Do you want to delete the original sheet?", vbYesNo + vbQuestion, "Delete Sheet")
If question = vbYes Then
Sheets(1).Activate
Sheets(1).Delete
Else
End If
Sheets.Add.Name = "Data"
Sheets("Contributors").Move After:=Sheets("Data")
Sheets.Add.Name = "Graph"
Sheets("Graph").Move After:=Sheets("Contributors")
Sheets("Data").Activate
Range("A1").Value = "Date/Time"
Range("B1").Value = "kW"
Range("C1").Value = "Amps"
' Yes, counter is 0-indexed here, and 1-indexed previously
' headerIndex does an absolute count of 0 To # targetCols, whereas index is relative
' If you change these, there is a non-zero chance that the For will throw an error
counter = 0
Sheets("Contributors").Activate
ActiveSheet.Range("A1").Select
For headerIndex = 0 To (UBound(targetCols) - LBound(targetCols))
ActiveCell.Value = replColNames(counter)
' If you don't use a Range, it fits columns based on headers, which isn't large enough
' A1:Z500 is a big enough sample to prevent that
ActiveCell.Range("A1:Z500").Columns.AutoFit
ActiveCell.Offset(0, 1).Select
counter = counter + 1
Next headerIndex
' Find column number with meters numbers, then assign its corresponding letter value
colNum = Application.WorksheetFunction.Match("Meter #", Range("A1:ZZ1"), 0)
colLetter = (Split(Cells(, colNum).Address, "$")(1))
rowCount = Range(colLetter & Rows.Count).End(xlUp).Row
'Range(colLetter & "2:" & colLetter & rowCount).Select
'Selection.SpecialCells(xlCellTypeBlanks).Select
'Selection.Delete Shift:=xlUp
' Meter numbers are 9 digits, so if one is shorter, assume a trimmed leading 0 and append it
For Each C In Range(colLetter & "2:" & colLetter & rowCount).Cells
' If cell type isn't set to text, the 0s will be non-visible, which while not an issue for the CSV, is confusing
' Note that this does not persist, as CSVs have no way of saving Excel's formatting
C.NumberFormat = "#"
cellLen = Len(C.Value)
If C.Value = "0" Or cellLen = 0 Then
C.Delete shift:=xlUp
End If
If cellLen < 9 Then
Set C.Value = 0 & C.Value
End If
Next C
question = MsgBox("Do you want to create a CSV file with meter numbers for use with MDMS?", vbYesNo + vbQuestion, "MDMS File")
If question = vbYes Then
' Call CopyMeters for use with MDMS
Sheets("Contributors").Activate
CopyMeters
Else
End If
End Sub
Sub CopyMeters()
Dim index As Integer
Dim fileSaveName As Variant
Dim rowCount As Variant
Dim colNum As Variant
Dim colLetter As Variant
Dim cellLen As Integer
colNum = Application.WorksheetFunction.Match("Meter #", Range("A1:ZZ1"), 0)
colLetter = (Split(Cells(, colNum).Address, "$")(1))
rowCount = Range(colLetter & Rows.Count).End(xlUp).Row
MsgBox ("Filename will automatically be appended with ""Meter List""")
fileSaveName = Split(ActiveWorkbook.Name, ".")
fileSaveName = fileSaveName(LBound(fileSaveName)) & " Meter List"
'For Each C In Range(colLetter & "2:" & colLetter & rowCount)
' C.NumberFormat = "#"
' cellLen = Len(C)
' If C.Value = "0" Or cellLen = 0 Then
' C.Delete shift:=xlUp
' End If
' If cellLen < 9 And cellLen <> 0 Then
' C.Value = "0" & C.Value
' End If
'Next C
Range(colLetter & "1:" & colLetter & rowCount).EntireColumn.Copy
Set newBook = Workbooks.Add
newBook.Worksheets("Sheet1").Range("A1").PasteSpecial (xlPasteAll)
Selection.Replace What:="0", Replacement:="", LookAt:=xlWhole, _
SearchOrder:=xlByColumns, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
Selection.Columns.AutoFit
newBook.SaveAs Filename:=fileSaveName, FileFormat:=xlCSV, CreateBackup:=False
End Sub
The error message is telling you that C is not an object. Therefore, you do not need the Set statement. Change your code to this:
If cellLen < 9 Then
C.Value = 0 & C.Value
End If
Why not just change the numberformat on the range? Or use a function for the value? A function would be something like
Public Function FormatValues(ByVal Input as String) as String
If Input <> vbNullString Then FormatValues = Format(Input, "000000000")
End Function
And it would be called like:
C.Value = FormatValues(C.Value)
But, if you're strictly interested in what the value looks like, and not as much as what the value is (since the leading zero will only be retained for strings) you could do something like this:
Public Sub FixFormats()
ThisWorkbook.Sheets("SomeSheet").Columns("A").NumberFormat = "000000000")
End Sub
This would format Column A of Worksheet "SomeSheet" to be of the format "0000000" which means numbers would look like "000000001", "000000002" so on so forth, regardless of whether something like "2" was actually entered.
I am trying to run a program that allows me to see what rooms in a college are free at a certain time in Microsoft excel.
The problem I am having is after I identify a empty class slot :
how doIi code it to go back up into the names of all the class rooms (All names are at Row 2)
and store the value of this.
I have tried offsetting but that wouldn't work for me.
I have added the Sample Data for further clarification
Public Sub EXq3()
Dim rnR1 As Range, roomNum As Integer
Const rooms = 13 ' Counter amount
Set rgR1 = ActiveCell.Offset(0, 1)
timeSolt = InputBox("What time") ' asks user what time to enter
Cells.find(What:=timeSolt, After:=ActiveCell, LookIn:=xlFormulas, LookAt:= _
xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False _
, SearchFormat:=False).Activate ' search and find code
For counter = 1 To rooms
If rgR1.Value = "" Then roomNum = rgR1.Offset(Range(2, rgR1.Value)) ' attempt at getting it to go to range 2
rgR1.Activate
Set rgR1 = rgR1.Offset(0, 1)
Next counter
MsgBox roomNum
End Sub
You probably by "go to range 2" mean "go to row 2", am I right? If yes, this is your solution:
For counter = 1 To rooms
If rgR1.Value = "" Then
roomNum = Cells(2, rgR1.Column).Value
End If
rgR1.Activate
Set rgR1 = rgR1.Offset(0, 1)
Next counter
EDIT
Ok, so I assume that you have some time options in column A, and some values for Room 1 in column B, Room 2 in column C etc. I have refactored your code to get rid of moving active cell. It is finding some time in column A and checking if there are some empty cells in row with this time option, and returns messages with numbers of this rooms.
My test sheet:
Code:
Public Sub EXq3()
Dim rnR1 As Range, roomNum As String, rooms As Integer Dim timeSolt As String
rooms = 13 ' Counter amount timeSolt = InputBox("What time") ' asks user what time to enter
Set rnR1 = ActiveSheet.Columns("A:A").Find(What:=timeSolt, LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False) ' search and find code
If rnR1 Is Nothing Then
MsgBox "Something is wrong with Input."
Else
For col = 2 To rooms + 1
If Cells(rnR1.Row, col).Value = "" Then
roomNum = Cells(2, col).Value
MsgBox roomNum
End If
Next col
End If
End Sub
So, i. e. when you type 17 in pop-up window, the result would be "Room 4" and "Room 10".
There is no need to Set rgR1 = ActiveCell.Offset(0, 1) , you can just search for the TimeSlot entered at the InputBox throughout your worksheet.
Also, it's better to stay away from Activate and ActiveCell and instead use referenced Ranges.
Since there is a possibility you have a few available room for a certain time, you need to store it as an array, and raise the index of rooms found on every match of ="".
There are more explanations inside the code comments below.
Code
Option Explicit
Public Sub EXq3()
Dim rnR1 As Range, roomNum As Variant, TimeSlot
Dim FindRng As Range, i As Integer, Counter As Integer
Const rooms = 13 ' Counter amount
ReDim roomNum(1 To 1000) ' init Rooms avaialable array to a large size
i = 1 '<-- reset Rooms Array index
TimeSlot = InputBox("What time") ' asks user what time to enter
Set FindRng = Cells.Find(What:=TimeSlot, After:=Range("A1"), LookIn:=xlFormulas, LookAt:= _
xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False _
, SearchFormat:=False) ' search and find TimeSlot
If Not FindRng Is Nothing Then '<-- was able to find the timeslot in the worksheet
For Counter = 1 To rooms
If Cells(FindRng.Row, Counter + 1).Value = "" Then '<-- add 1 to counter since starting from Column B
roomNum(i) = Cells(2, Counter + 1).Value '<-- save room number inside the array
i = i + 1
End If
Next Counter
ReDim Preserve roomNum(1 To i - 1) ' <-- resize array back to number of available rooms found
' loop through all available rooms in the array, and show a msgbox for each one
For i = 1 To UBound(roomNum)
MsgBox "Room number " & roomNum(i) & " is available at " & TimeSlot
Next i
Else '<-- could bot find the timeslot in the worksheet
MsgBox "Couldn't find " & TimeSlot & " inside the worksheet!"
End If
End Sub
you could try this:
Public Sub EXq3()
Dim rnR1 As Range
Dim rooms As Integer
Dim timeSolt As String, roomNum As String
rooms = 13 ' Counter amount
With ActiveSheet
Do
timeSolt = Application.InputBox("What time", "Input time", Type:=2)
If timeSolt = CStr(False) Then Exit Sub '<--| exit if user cancels the dialogbox
Set rnR1 = .Columns("A:A").SpecialCells(XlCellType.xlCellTypeConstants, xlTextValues).Find(What:=timeSolt, LookIn:=xlValues, LookAt:=xlWhole, MatchCase:=False, SearchFormat:=False) ' search and find code
If Not rnR1 Is Nothing Then Exit Do
MsgBox timeSolt & " is not a vaild time" & vbCrLf & vbCrLf & "please try again"
Loop
With .Range(rnR1.Offset(, 1), .Cells(rnR1.Row, .Columns.count).End(xlToLeft))
If WorksheetFunction.CountBlank(.Cells) = 0 Then
MsgBox "Sorry! No rooms left for the input time"
Else
roomNum = .Parent.Cells(2, .SpecialCells(xlCellTypeBlanks).Cells(1, 1).Column)
MsgBox "First room available at " & timeSolt & " is room " & roomNum
End If
End With
End With
End Sub
For context:
I would like for the program to look through column B, identify the first "< / >" (which is purely stylistic and can be changed if necessary - it's only used to break up the data) as the start of a week at cell B9 and the next "< / >" (end of the week) at B16. So the range I'm interested in is B10-B15. It would then sum those numbers from J10 to J15 (Earned column) and paste that sum in L16 (Week Total column). The same could then be done with 'Hours' and 'Week Hours'. For the following week (and thereafter) the 'end of the week' "< / >" becomes the start of the week, and the program continues until B200.
I don't have any experience with VBA and so made the following incomplete attempt (based on what I had found online) but felt too out of my depth not to ask for help.
Sub Work()
Dim rng As Range
Dim rngFound As Range
Set rng = Range("B:B")
Set rngFound = rng.Find("</>")
If rngFound Is "</>" Then
If Cell = "</>" Then
End If
End Sub
Thank you for any help and please let me know if I can be clearer or elaborate on something.
The following code will loop through 200 lines, looking for your symbol. When found, it will sum the numbers in column J for rows between the current row and the last symbol.
I've included two lines that will update the formula. To me, the 2nd one is easier to understand.
Sub Work()
Dim row As Integer
row = 4
Dim topRowToAdd As Integer 'Remember which row is the
'top of the next sum
topRowToAdd = 4
While row <= 200
If Cells(row, 2) = "</>" Then
'Cells(row, 10).FormulaR1C1 = "=SUM(R[" & -(row - topRowToAdd) & "]C[0]:R[" & -1 & "]C[0])"
Cells(row, 10).Value = "=SUM(J" & topRowToAdd & ":J" & row - 1 & ")"
topRowToAdd = row + 1
End If
row = row + 1
Wend
End Sub
Sub Work()
Dim rng As Range, rngFound As Range
Set rng = Range("B:B")
Set rngFound = rng.Find("</>")
If rngFound.Value2 = "</>" Then
'whatever you want to do
End If
End Sub
So at a second glance it looks like this. If you'd like to make it structured you'd need to use a countifs function first.
Sub Work()
Dim rng As Range, rngFound(1) As Range
Set rng = Range("B1:B200")
On Error GoTo Err 'it is quite possible it will run into an error if there are no matches and I'm too lazy for structured solution
Set rngFound(0) = rng.Find(What:="</>", LookAt:=xlWhole, SearchDirection:=xlNext) 'finds the first
Set rngFound(1) = rng.Find(What:="</>", LookAt:=xlWhole, SearchDirection:=xlNext, After:=rngFound(0)) 'finds the first after the first (i.e. the second)
Set rngFound(0) = rngFound(0).Offset(1, 8) '8 is the difference between B and J, row shifts as per description, I advise you to make it a variable
Set rngFound(1) = rngFound(1).Offset(-1, 8)
If rngFound(1).Row > rngFound(0).Row Then 'if it's not higher, then it recurred and found the first range again
rngFound(1).Offset(1, 2).Formula = "=SUM(" & Range(rngFound(0), rngFound(1)).Address & ")" 'L column will have the sum as a formula
Else
MsgBox "There is a single match in " & rng.Address(False, False)
End If
If False Then
Err:
MsgBox "There are no matches in " & rng.Address(False, False)
End If
End Sub
Now for the grand finale:
Sub Work()
Dim rng As Range, rngFound() As Range, rngdiff(1) As Long, rngcount As Long
Set rng = Range("B1:B200")
rngcount = rng.Cells.Count
ReDim rngFound(rngcount)
rngdiff(0) = Range("J1").Column - rng.Column ' the range that needs to be summed is in column J
rngdiff(1) = Range("L1").Column - rng.Column ' the range containing the formula is in column L
On Error GoTo Err 'it is quite possible it will run into an error if there are no matches and I'm too lazy for structured solution
Set rngFound(0) = rng.Find(What:="</>", LookAt:=xlWhole, SearchDirection:=xlNext) 'finds the first
'loop starts
For i = 1 To rngcount
Set rngFound(i) = rng.Find(What:="</>", LookAt:=xlWhole, SearchDirection:=xlNext, After:=rngFound(i - 1)) 'finds the next
If rngFound(i).Row > rngFound(i - 1).Row Then 'if it's not higher, then it recurred and found the first range again
rngFound(i).Offset(0, rngdiff(1)).Formula = "=SUM(" & Range(rngFound(i - 1).Offset(1, rngdiff(0)), rngFound(i).Offset(-1, rngdiff(0))).Address & ")" 'L column will have the sum as a formula
Else
Exit Sub 'if it recurred the deed is done
End If
Next i
If False Then
Err:
MsgBox "There are no matches in " & rng.Address(False, False)
End If
End Sub