How to format time in an Array - arrays

I am creating a text-box using an array so that when someone searches a value in 1 column, they get the results from the other 3. For some reason, although the time for "CallTime"/"RequestedCallTime" is formatted "h:mm:ss" on excel, it is coming through as a decimal in the textbox.
Private Sub Workbook_Open()
Dim PostalCode() As String
Dim CallReason() As String
Dim CallDate() As String
Dim CallTime() As String
Dim wsdata As Worksheet
Dim i As Integer
Dim found As Boolean
Dim requestedCode As String
Dim requestedCallReason As String
Dim requestedCallDate As String
Dim requestedCallTime As String
Dim nProducts As Integer
Set wsdata = Worksheets("Toronto311Data")
' Find the number of products, redimension the arrays, and fill them
' with the data in the lists.
With wsdata.Range("A1")
nProducts = Range(.Offset(1, 0), .End(xlDown)).Rows.Count
ReDim PostalCode(1 To nProducts)
ReDim CallReason(1 To nProducts)
ReDim CallTime(1 To nProducts)
ReDim CallDate(1 To nProducts)
For i = 1 To nProducts
PostalCode(i) = .Offset(i, 0).Value
CallReason(i) = .Offset(i, 2).Value
CallDate(i) = .Offset(i, 4).Value
CallTime(i) = .Offset(i, 5).Value
Next
End With
' Get a postal code from the user.
requestedCode = InputBox("Enter the first 3 digits of the postal code (UpperCase Letters Please).")
' Look for the code in the list. Record its unit price if it is found.
found = False
For i = 1 To nProducts
If PostalCode(i) = requestedCode Then
found = True
requestedCallReason = CallReason(i)
requestedCallDate = CallDate(i)
requestedCallTime = CallTime(i)
Exit For
End If
Next
' Display an appropriate message.
If found Then
MsgBox "The call reason of postal code " & requestedCode & " is " & requestedCallReason & ". The call date/time is " & requestedCallDate & " and the call time is " & requestedCallTime & ".", vbInformation, "Information found"
Else
MsgBox "The Postal Code " & requestedCode & " is not on the list.", _
vbInformation, "Information not found"
End If
End Sub

It might be that the spreadsheet is converting the time to a unix style time which is seconds since 1 January 1970. You might want to force the format of those cells to be a string.

Dates are numeric values. Simply format the cells value.
CallTime(i) = Format(.Offset(i, 5).Value, "h:mm:ss")

Related

Subscript out of range when trying to loop through array to read values

I have a string of predefined worksheets, that I need to run specific code for. I get a compile error.
The code is set up to copy data from one sheet to another.
How do I do the same for multiple sheets?
When I step through the code sht is showing the MHP60,MHP61,MHP62 and not just MHP60.
I get a subscript out of range error.
Sub Prepare_CYTD_Report()
Dim addresses() As String
Dim addresses2() As String
Dim SheetNames() As String
Dim SheetNames2() As String
Dim wb1 As Workbook, wb2 As Workbook
Dim my_Filename
'Declare variables for MHP60, MHP61, MHP62 Trial Balance Values
Dim i, lastcol As Long
Dim tabNames, cell As Range
Dim tabName As String
Dim sht As Variant
addresses = Strings.Split("A9,A12:A26,A32:A38,A42:A58,A62:A70,A73:A76,A83:A90", ",") 'Trial Balance string values
addresses2 = Strings.Split("G9,G12:G26,G32:G38,G42:G58,G62:G70,G73:G76,G83:G90", ",") 'Prior Month string values
SheetNames = Strings.Split("MHP60,MHP61,MHP62")
'SheetNames2 = Strings.Split("MHP60-CYTDprior,MHP61-CYTDprior,MHP62-CYTDprior")
Set wb1 = ActiveWorkbook 'Revenue & Expenditure Summary Workbook
'*****************************Open CYTD files
my_Filename = Application.GetOpenFilename(fileFilter:="Excel Files,*.xl*;*.xm*", Title:="Select File to create CYTD Reports")
If my_Filename = False Then
Exit Sub
End If
Application.ScreenUpdating = False
Set wb2 = Workbooks.Open(my_Filename)
'*****************************Load Column Header Strings & Copy Data
For Each sht In SheetNames
lastcol = wb1.Sheets(sht).Cells(5, Columns.Count).End(xlToLeft).Column
On Error Resume Next
Set tabNames = wb1.Sheets(sht).Cells(4, 3).Resize(1, lastcol - 2).SpecialCells(xlCellTypeConstants)
'actual non-formula text values on row 4 from column C up to column lastCol'
On Error GoTo 0
If Err.Number <> 0 Then
MsgBox "No headers were found on row 4 of MHP60", vbCritical
Exit Sub
End If
For Each cell In tabNames
tabName = Strings.Trim(cell.Value2)
'dedicated variable in case of requirement for further parsing (space/comma elimination?)'
If CStr(wb1.Sheets(sht).Evaluate("ISREF('[" & wb2.Name & "]" & tabName & "'!$A$1)")) = "True" Then
'If wb2 has a tab named for the value in tabName
For i = 0 To UBound(addresses)
wb2.Sheets(tabName).Range(addresses(i)).Value2 = wb1.Sheets(sht).Range(addresses(i)).Offset(0, cell.Column - 1).Value2
'Debug.Print "data for " & wb2.Sheets(tabName).Range(addresses(i)).Address(, , , True) & " copied from " & wb1.Sheets("MHP60").Range(addresses(i)).Offset(0, cell.Column - 1).Address(, , , True)
Next i
Else
Debug.Print "A tab " & tabName & " was not found in " & wb2.Name
End If
Next cell
Next sht
MsgBox "CYTD Report Creation Complete", vbOKOnly
Application.ScreenUpdating = True
End Sub
Split by what?
SheetNames = Strings.Split("MHP60,MHP61,MHP62")
Split by comma? Then use the following instead:
SheetNames = Strings.Split("MHP60,MHP61,MHP62", ",")
Alternative
Dim SheetNames() As Variant ' needs to be Variant to work with Array()
SheetNames = Array("MHP60", "MHP61", "MHP62")
This should be quicker as your macro does not need to split the string and has it as array directly.

How do I extract the last name from each cell in a name column and assign it to name array?

I think i've got a good start, but I'm having a tough time taking this to the finish line. Could someone help me out?
I have a name column(G) in my spreadsheet. I want to pull the only the last name out of each cell and assign it to an array called name_array.
I know that my If function is working because if I set each name_cell to the LastName variable it substitutes only the lastname in each cell of the column, but I cannot figure out how to assign that to the array.
Here is my code thus far. Can someone please help me out and point out what I'm missing?
Sub create_namear()
Dim name_array() As Variant
Dim name_range As Range
Dim name_cell As Range
Dim n As Long
Set name_range = ActiveSheet.Range("G2:G" & Range("G" & Rows.Count).End(xlUp).Row)
ReDim name_array(name_range.Cells.Count)
For Each name_cell In name_range.Cells
Dim Lastname As String
If InStr(name_cell, " ") > 0 Then
Lastname = Split(name_cell, " ")(1)
End If
name_array(n) = lastname.value
n = n + 1
Next name_cell
Debug.Print name_array(1)
End Sub
Name Column
Here is another way to achieve what you want without looping. I have commented the code so you should not have a problem understanding it.
BASIC LOGIC
To get the part after SPACE, you can use the formula =IFERROR(MID(G2,SEARCH(" ",G2,1),LEN(G2)-SEARCH(" ",G2,1)+1),"")
Now applying the formula in the entire range and getting the value using INDEX(FORMULA). You can find the explanation of this method in Convert an entire range to uppercase without looping through all the cells
CODE
Option Explicit
Sub Sample()
Dim ws As Worksheet
Dim rng As Range
Dim lRow As Long, i As Long
Dim FinalAr As Variant
'~~> Set this to the relevant sheet
Set ws = Sheet1
With ws
'~~> Find last row in col G
lRow = .Range("G" & .Rows.Count).End(xlUp).Row
'~~> Set your range
Set rng = .Range("G2:G" & lRow)
'~~> Get all the last names from the range and store them
'~~> in an array in 1 go!
FinalAr = Evaluate("index(IFERROR(MID(" & _
rng.Address & _
",SEARCH("" ""," & _
rng.Address & _
",1),LEN(" & _
rng.Address & _
")-SEARCH("" ""," & _
rng.Address & _
",1)+1),""""),)")
End With
'~~> Check the output
For i = LBound(FinalAr) To UBound(FinalAr)
Debug.Print ">"; FinalAr(i, 1)
Next i
End Sub
IN ACTION
ALTERNATIVE METHODS
Use Text To columns and then store the output in an array
Use Flash Fill to get the last names and then store the output in an array. One drawback of this method is that the names which do not have last name, it will show first name instead of a blank.
Sub create_namear()
Dim name_array() As Variant
Dim name_range As Range
Dim name_cell As Range
Dim n As Long
Set name_range = ActiveSheet.Range("G2:G" & Range("G" & Rows.Count).End(xlUp).Row)
ReDim name_array(0 to name_range.Cells.Count-1) '### 0-based array...
For Each name_cell In name_range.Cells
If InStr(name_cell, " ") > 0 Then
name_array(n) = Split(name_cell, " ")(1) 'simplify...
End If
n = n + 1
Next name_cell
Debug.Print name_array(1)
End Sub
Solution using Filter() (values with missing lastnames are excluded):
Sub ExtractLastNames()
Dim arr, name_array, i
arr = WorksheetFunction.Transpose(Range("G2:G" & Cells(Rows.Count, "G").End(xlUp).Row)) 'first, get the horizontal one-dimentional array from cells
name_array = Filter(arr, " ", True) 'second, filter out one-word and empty elements
For i = LBound(name_array) To UBound(name_array)
name_array(i) = Split(name_array(i))(1) 'third, replace name_array values with extracted lastnames
Next
Range("H2").Resize(UBound(name_array) + 1) = WorksheetFunction.Transpose(name_array) ' output
End Sub
Last Names to Array
The following will consider the substring after the last occurring space as the last name.
Option Explicit
Sub create_namear()
Dim ws As Worksheet: Set ws = ActiveSheet
Dim nRange As Range
Set nRange = ws.Range("G2:G" & ws.Range("G" & ws.Rows.Count).End(xlUp).Row)
Dim rCount As Long: rCount = nRange.Rows.Count
Dim nArray() As String: ReDim nArray(0 To rCount - 1)
Dim nCell As Range
Dim n As Long
Dim nmLen As Long
Dim LastSpacePosition As Long
Dim nmString As String
Dim LastName As String
For Each nCell In nRange.Cells
nmString = CStr(nCell.Value)
If InStr(1, nmString, " ") > 0 Then
LastSpacePosition = InStrRev(nCell.Value, " ")
nmLen = Len(nmString)
If LastSpacePosition < nmLen Then
LastName = Right(nmString, nmLen - LastSpacePosition)
nArray(n) = LastName
n = n + 1
End If
End If
Next nCell
If n = 0 Then Exit Sub
If n < rCount Then
ReDim Preserve nArray(0 To n - 1)
End If
Debug.Print "[" & LBound(nArray) & "," & UBound(nArray) & "]" _
& vbLf & Join(nArray, vbLf)
End Sub
Extension on Siddharth' s formula evaluation
These additions to Siddharth's valid code can be helpful, if there are less than 2 data rows in order to avoid
an unwanted evaluation of the title row 1:1 (in case of no data at all, see section 1.b) - This can be prevented by correcting a resulting row number lRow of only 1 to the actual data row start of 2.
Error 9 Subscript out of range (in case of a single element; see section 3.b) - Note that this requires to transform a 1-dim result to a 2-dim results array by means of a adequately dimensioned tmp array.
Furthermore I simplified the formula building to avoid repeated rng.Address insertions just to show another way of doing it (see section 2.).
Sub GetLastName()
'0. Set this to the relevant sheet
Dim ws As Worksheet: Set ws = Sheet1
With ws
'1. Define data range
'1. a) Find last row in col G
Dim lRow As Long
lRow = .Range("G" & .Rows.count).End(xlUp).Row
'1. b) Provide for empty data set ' << Added to avoid title row evaluation
If lRow = 1 Then lRow = 2
'1. c) Set your range
Dim rng As Range: Set rng = .Range("G2:G" & lRow)
'2. Define formula string parts ' << Modified for better readibility
Dim FormulaParts()
FormulaParts = Array("INDEX(IFERROR(MID(", _
",SEARCH("" "",", _
",1),LEN(", _
")-SEARCH("" "",", _
",1)+1),""""),)")
'3. Assign last names to 2-dim array results
'3. a) Get all the last names from the range and store them
Dim results
results = Evaluate(Join(FormulaParts, rng.Address))
End With
'3.b) Provide for single results '<< Added to avoid Error 9 Subscript o/Rng
If UBound(results) = 1 Then '<< Force single element into 2-dim array
Dim tmp(1 To 1, 1 To 1)
tmp(1, 1) = results(1)
results = tmp
End If
'h) Display in VB Editor's immediate window
Dim i As Long
For i = LBound(results) To UBound(results)
Debug.Print ">"; results(i, 1)
Next i
'i) Write last names to target '<< Added to demonstrate writing back
ws.Range("H2").Resize(UBound(results), 1) = results
End Sub

Using VBA, print an array made in Word to Excel

I am a VBA novice and I am trying to print an array that I was able to make (basically copying from another post) in VBA today. I placed a break into the script and inspected the array in the locals page to see that the array captures what I want (and some extra data that I will filter out). I spent the day reading about printing arrays on stack overflow and other sites and I ended up a bit lost. My goal is to export the array as a table in excel.
The script looks for underlined sentences in a 400 page word document and places them into the array. All that's really necessary for printing is the underlined sentences, so maybe an array wasn't the best approach? How can I export the array 'myWords' to a fresh excel document or one that I designate?
Many thanks for your help!
Sub addUnderlinedWordsToArray()
On Error GoTo errhand:
Dim myWords() As String
Dim i As Long
Dim myDoc As Document: Set myDoc = ActiveDocument ' Change as needed
Dim aRange As Range: Set aRange = myDoc.Content
Dim sRanges As StoryRanges: Set sRanges = myDoc.StoryRanges
Dim ArrayCounter As Long: ArrayCounter = 0 ' counter for items added to the array
Dim Sentence As Range
Dim w As Variant
Application.ScreenUpdating = False
ReDim myWords(aRange.Words.Count) ' set a array as large as the
' number of words in the doc
For Each Sentence In ActiveDocument.StoryRanges
For Each w In ActiveDocument.Sentences
If w.Font.Underline <> wdUnderlineNone Then
myWords(ArrayCounter) = w
ArrayCounter = ArrayCounter + 1
End If
Next
Next
Set myDoc = Nothing
Set aRange = Nothing
Set sRange = Nothing
Application.ScreenUpdating = True
Exit Sub
errhand:
Application.ScreenUpdating = True
MsgBox "An unexpected error has occurred." _
& vbCrLf & "Please note and report the following information." _
& vbCrLf & "Subroutine Name: addUnderlinedWordsToArray" _
& vbCrLf & "Error Number: " & Err.Number _
& vbCrLf & "Error Description: " & Err.Description _
, vbCritical, "Error!"
End Sub
I prefer to use Late Binding over adding an external reference to Excel. This will allow the code to work properly no mater what version of Office is installed.
Sub addUnderlinedWordsToArray()
On Error GoTo errhand:
Dim myWords() As String
Dim i As Long
Dim myDoc As Document: Set myDoc = ActiveDocument ' Change as needed
Dim aRange As Range: Set aRange = myDoc.Content
Dim sRanges As StoryRanges: Set sRanges = myDoc.StoryRanges
Dim ArrayCounter As Long: ArrayCounter = 0 ' counter for items added to the array
Dim Sentence As Range
Dim w As Variant
Application.ScreenUpdating = False
ReDim myWords(aRange.Words.Count) ' set a array as large as the
' number of words in the doc
For Each Sentence In ActiveDocument.StoryRanges
For Each w In ActiveDocument.Sentences
If w.Font.Underline <> wdUnderlineNone Then
myWords(ArrayCounter) = w
ArrayCounter = ArrayCounter + 1
End If
Next
Next
ReDim Preserve myWords(ArrayCounter - 1)
AddWordsToExcel myWords
Set myDoc = Nothing
Set aRange = Nothing
Set sRange = Nothing
Application.ScreenUpdating = True
Exit Sub
errhand:
Application.ScreenUpdating = True
MsgBox "An unexpected error has occurred." _
& vbCrLf & "Please note and report the following information." _
& vbCrLf & "Subroutine Name: addUnderlinedWordsToArray" _
& vbCrLf & "Error Number: " & Err.Number _
& vbCrLf & "Error Description: " & Err.Description _
, vbCritical, "Error!"
End Sub
Sub AddWordsToExcel(myWords() As String)
Dim xlApp As Object
Set xlApp = CreateObject("Excel.Application")
Dim wb As Object
Set wb = xlApp.Workbooks.Add
wb.Worksheets(1).Range("A1").Resize(UBound(myWords) + 1).Value = xlApp.Transpose(myWords)
xlApp.Visible = True
End Sub
This is tested and working fine :
Option Explicit
Sub addUnderlinedWordsToArray()
Dim myWords() As String
Dim i As Long
Dim myDoc As Document: Set myDoc = ActiveDocument ' Change as needed
Dim aRange As Range: Set aRange = myDoc.Content
Dim sRanges As StoryRanges: Set sRanges = myDoc.StoryRanges
Dim ArrayCounter As Long: ArrayCounter = 0 ' counter for items added to the array
Dim Sentence As Range
Dim w As Variant
Dim Ex0 As Excel.Application
Dim Wb0 As Workbook
Application.ScreenUpdating = False
On Error GoTo errhand:
For Each Sentence In ActiveDocument.StoryRanges
For Each w In ActiveDocument.Sentences
If w.Font.Underline <> wdUnderlineNone Then
ReDim Preserve myWords(ArrayCounter)
myWords(ArrayCounter) = w
ArrayCounter = ArrayCounter + 1
End If
Next
Next
On Error GoTo 0
Set myDoc = Nothing
Set aRange = Nothing
Set sRanges = Nothing
Set Ex0 = New Excel.Application
Set Wb0 = Ex0.workbooks.Add
Ex0.Visible = True
Wb0.Sheets(1).Range("A1").Resize(UBound(myWords) + 1, 1) = WorksheetFunction.Transpose(myWords)
Application.ScreenUpdating = True
Debug.Print UBound(myWords())
Exit Sub
errhand:
Application.ScreenUpdating = True
MsgBox "An unexpected error has occurred." _
& vbCrLf & "Please note and report the following information." _
& vbCrLf & "Subroutine Name: addUnderlinedWordsToArray" _
& vbCrLf & "Error Number: " & Err.Number _
& vbCrLf & "Error Description: " & Err.Description _
, vbCritical, "Error!"
End Sub
Make sure to have the Microsoft Excel 14.0 Object Library ticked in Tools/References
The code provided in the question has some problems, which I've tried to correct as per the problem description.
The code declares a number of object variables, assigning them in the same line as the declaration, but these objects are never used. In order to improve code readability and make these objects "obvious" I've moved the instantiations to new lines.
The sample code below then substitutes these objects for the ActiveDocument... objects used in the original code, where these objects are intended to be used. This makes the code more readabile and more efficient.
The use of StoryRanges is questionable in the context of the code. StoryRanges are not the same as Sentences. On the assumption that the use of StoryRanges was a misunderstanding or typo, I've changed the code to use Sentences. If StoryRanges is meant, the code can loop through them, but certain structural changes would be required. (StoryRanges enables code to access all parts of a document such as TextBoxes, Headers, Footers, Endnotes - instead of just the main body of the document.)
It makes no sense to loop sentences while sizing the array to the number of words in the document. This has been changed to the number of sentences, which will require less memory.
Only the text, not the entire sentence Range should be added to the array since Excel can't do anything with a Word.Range except accept its text. This will require less memory.
On the assumption that not every sentence in the document is underlined, it's not necessary to maintain an array with empty members, so after the loop the array is resized to contain only those that have been populated. (ReDim Preserve myWords(ArrayCounter - 1)). This will avoid writing "empty" content to the Excel worksheet.
The code to write to Excel is in a separate procedure, making it re-usable for other arrays that might need to be transferred to Excel. The code has been written as late-binding, making it independent of requiring a reference to the Excel library. If early-binding (with a reference) is desired, those declarations are commented out in-line.
The writing to Excel only occurs if the array contains members. If ArrayCounter has never been incremented, the call to the other procedure is not performed.
The Excel objects are set to Nothing at the end of that procedure.
Note: The code posted in the question and used here picks up any sentence that contains an underline.
Sample code:
Sub addUnderlinedWordsToArray()
On Error GoTo errhand:
Dim myWords() As String
Dim i As Long
Dim myDoc As Document
Dim aRange As Range
Dim sRanges As Sentences
Dim ArrayCounter As Long ' counter for items added to the array
Dim Sentence As Range
Dim w As Variant
Application.ScreenUpdating = False
Set myDoc = ActiveDocument ' Change as needed
Set aRange = myDoc.content
Set sRanges = myDoc.Sentences
ArrayCounter = 0
ReDim myWords(aRange.Sentences.Count - 1) ' set a array as large as the
' number of sentences in the doc
For Each Sentence In sRanges
If Sentence.Font.Underline <> wdUnderlineNone Then
myWords(ArrayCounter) = Sentence.text
ArrayCounter = ArrayCounter + 1
End If
Next
If ArrayCounter > 0 Then
ReDim Preserve myWords(ArrayCounter - 1)
WriteToExcel myWords
End If
Set myDoc = Nothing
Set aRange = Nothing
Set sRanges = Nothing
Application.ScreenUpdating = True
Exit Sub
errhand:
Application.ScreenUpdating = True
MsgBox "An unexpected error has occurred." _
& vbCrLf & "Please note and report the following information." _
& vbCrLf & "Subroutine Name: addUnderlinedWordsToArray" _
& vbCrLf & "Error Number: " & Err.Number _
& vbCrLf & "Error Description: " & Err.Description _
, vbCritical, "Error!"
End Sub
Sub WriteToExcel(a As Variant)
Dim appExcel As Object 'Excel.Application
Dim wb As Object ' Excel.Workbook
Dim r As Object ' Excel.Range
Dim i As Long
Set appExcel = CreateObject("Excel.Application")
appExcel.Visible = True
appExcel.UserControl = True
Set wb = appExcel.Workbooks.Add
Set r = wb.Worksheets(1).Range("A1")
r.Resize(UBound(myWords) + 1).Value = xlApp.Transpose(myWords)
Set r = Nothing
Set wb = Nothing
Set appExcel = Nothing
End Sub
The general answer is to use Range ("A1") = myWords(ArrayCounter)
You would need to step through the array while simultaneously moving to the next cell.
You could also use Range ("A1:B3") = myWords.

How to work with arrays and display them in a MsgBox VBA

I need to write a sub that take a single argument from an input box that searches a stock price in a list. The sub searches down the list of prices from "B3:B20" and when it finds the first price that exceeds this price it displays the date which is displays in the column next to it in column A in a msgbox. This is the code I have so far but I am having trouble figuring out how to display the corresponding data for the price found:(I believe the problem has to do with the array created)
Sub RecordHigh1()
Dim searchPrice As Currency
Dim rng As Range
Dim date1() As String
Dim price() As String
Dim nDates As Integer
Dim i As Integer
With wsData.Range("A3")
nDates = Range("A3", Range("A3").End(xlDown).Value)
ReDim date1(1 To nDates)
ReDim price(1 To nDates)
For i = 1 To nDates
date1(i) = .Offset(i, 0).Value
price(i) = .Offset(i, 1).Value
Next
End With
searchPrice = InputBox("Enter a Price")
Set rng = Range("B3", Range("B3").End(xlDown).Address)
For Each cell In rng
If cell.Value > searchPrice Then
MsgBox "The first date WalTech stock price exceeded " & searchPrice & " was & date(i) =.Offset(i, 0).Value & "
Else
MsgBox "WalTech stock has not exceeded this price"
End If
Next
End Sub
Option Explicit
Sub RecordHigh1()
Dim searchPrice As Currency
Dim rng As Range
Dim date1() As String
Dim price() As String
Dim nDates As Long
Dim i As Long '<~~ always better to use Long type instead of integer
Dim cell As Range
'With wsData.Range("A3")'<~~ wsData is not defined. or is it a Public variable?
With ActiveSheet.Range("A3") '<~~ otherwise set it to a specific sheet: With Worksheets("MySheet").Range("A3")
nDates = .Range(.Cells, .Range("A3").End(xlDown)).Rows.Count
ReDim date1(1 To nDates)
ReDim price(1 To nDates)
With .Range("A3")
For i = 1 To nDates
date1(i) = .Offset(i, 0).Value
price(i) = .Offset(i, 1).Value
Next i '<~~ always better to type the variable you want to iterate on
End With
End With
searchPrice = InputBox("Enter a Price")
Set rng = ActiveSheet.Range("B3", ActiveSheet.Range("B3").End(xlDown).Address)'<~~ better to add sheet reference (ActiveSheet or Worksheets("MySheet") or wsData, this latter once you define it)
For Each cell In rng
If cell.Value > searchPrice Then
MsgBox "The first date WalTech stock price exceeded " & searchPrice & " was " & cell.Offset(, -1)
Else
MsgBox "WalTech stock has not exceeded this price"
End If
Next cell '<~~ always better to type the variable you want to iterate on
End Sub

Why is my array being cleared?

I'm designing a slide checker to look for mismatched fonts and colours, and need to keep track of each colour for each shape in an array. My problem is that for some reason the array get's cleared. I've put in flags to check that the array is being properly assigned. As it moves through the loop, it correctly adds 1 to the array, updates the colour for that index, then moves forward. For some reason when it gets to the msgbox check, the array still has the correct number of indexes, but the array is empty for every shape except for the last shape in the loop. For example one shape has 5 lines, another shape has 2. I'll get a msgbox 7 times, but the first 5 are empty, and the next 2 have the actual colour.
Private Sub CommandButton1_Click()
Dim x As Integer
Dim i As Integer
Dim a As Integer
Dim b As Integer
Dim shpCount As Integer
Dim lFindColor As Long
Dim oSl As Slide
Dim oSh As Shape
Dim colorsUsed As String
Dim fontsUsed As String
Dim lRow As Long
Dim lCol As Long
Dim shpFont As String
Dim shpSize As String
Dim shpColour As String
Dim shpBlanks As Integer: shpBlanks = 0
Dim oshpColour()
Set oSl = ActiveWindow.View.Slide
For Each oSh In oSl.Shapes
'----Shape Check----------------------------------------------------------
With oSh
If .HasTextFrame Then
If .TextFrame.HasText Then
shpCount = shpCount + .TextFrame.TextRange.Runs.Count
ReDim oshpColour(1 To shpCount)
For x = 1 To .TextFrame.TextRange.Runs.Count
a = a + 1
oshpColour(a) = .TextFrame.TextRange.Runs(x).Font.Color.RGB
shpFont = shpFont & .TextFrame.TextRange.Runs(x).Font.Name & ", "
shpSize = shpSize & .TextFrame.TextRange.Runs(x).Font.Size & ", "
shpColour = shpColour & .TextFrame.TextRange.Runs(x).Font.Color.RGB & ", "
Next
End If
End If
Next
MsgBox "Shape Fonts: " & shpFont & vbCrLf & "Shape Font Sizes: " & shpSize & vbCrLf & "Shape Font Colours: " & shpColour
For b = LBound(oshpColour) To UBound(oshpColour)
MsgBox oshpColour(b)
Next
End Sub
The right way to redim an array keeping it content is as follows:
ReDim Preserve oshpColour(1 To shpCount)

Resources