VBA Calculate percentage - excel

So i need some help. Im pretty new to VBA so im having some trouble.
Well i have multiple sheets in my work book (excel). what im trying to do is, calculate the percentage of how many cells have the word "IMCOMPLETE" in column D and putting the outcome in the main sheet on a certain cell. Example:
Sub Get_Percentage()
If Range("Jackson,_Mr._Vince_R.TrainingSt'!D2:D100").Value = "IMCOMPLETE" Then
put outcome in "TotalSummery%"!E2
If Range("Carter,_Mr._Oscar_R_(Oscar)Trai'!D2:D100").Value = "IMCOMPLETE" Then
put outcome in "TotalSummery%"!E4
If Range("Taravella,_Mr._Jim_(Jim)Trainin'!D2:D100") Value = "IMCOMPLETE" Then
put outcome in "TotalSummery%"!E5
End Sub
FYI: I have like 10 sheet tabs. Not sure if this would be a macro.

Sub FindAndCountWordInExcelWorkBook(Byval SearchString As String)
SearchString = "IMCOMPLETE"
Dim oRange As Range, aCell As Range, bCell As Range
Dim ws As Worksheet
Dim ExitLoop As Boolean
Dim FoundAt As String
On Error GoTo Err
Dim i As Integer
For i = 1 To Worksheets.Count
Set ws = Worksheets(i)
Set oRange = ws.UsedRange
Dim CountOfKeyWord As Integer
Set aCell = oRange.Find(What:=SearchString, LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False)
If Not aCell Is Nothing Then
Set bCell = aCell
FoundAt = aCell.Address
Do While ExitLoop = False
Set aCell = oRange.FindNext(After:=aCell)
If Not aCell Is Nothing Then
If aCell.Address = bCell.Address Then Exit Do
CountOfKeyWord = CountOfKeyWord + 1
FoundAt = FoundAt & ", " & aCell.Address
Else
ExitLoop = True
End If
Loop
Else
' MsgBox SearchString & " not Found"
End If
Next i
MsgBox "The Search String: " & SearchString & ", appeared " & CountOfKeyWord & " times at these locations: " & FoundAt
Exit Sub
Err:
MsgBox Err.Description
End Sub

Here is a simple way to do it. I am doing it for one sheet. You can use it in a loop
Sub Sample()
Dim ws As Worksheet
Dim SearchText As String
Dim WordCount As Long, ColDTotalWordCount As Long
Dim PercentageWord As Double
Set ws = ThisWorkbook.Sheets("Sheet1")
SearchText = "IMCOMPLETE"
With ws
'~~> Count the occurances of the word "IMCOMPLETE"
WordCount = Application.WorksheetFunction.CountIf(.Columns(4), SearchText)
'~~> Count the total words in Col D
ColDTotalWordCount = Application.WorksheetFunction.CountA(.Columns(4))
'~~> Calculate Percentage
PercentageWord = WordCount / ColDTotalWordCount
Debug.Print Format(PercentageWord, "00.00%")
End With
End Sub
The above code can be also converted to a function which can be very useful when you are looping through the sheets.
Option Explicit
Sub Sample()
Dim wSheet As Worksheet
Dim TextToSearch As String
Set wSheet = ThisWorkbook.Sheets("Sheet1")
TextToSearch = "IMCOMPLETE"
Debug.Print GetPercentage(wSheet, TextToSearch)
End Sub
Function GetPercentage(ws As Worksheet, SearchText As String) As String
Dim WordCount As Long, ColDTotalWordCount As Long
Dim PercentageWord As Double
With ws
'~~> Count the occurances of the word "IMCOMPLETE"
WordCount = Application.WorksheetFunction.CountIf(.Columns(4), SearchText)
'~~> Count the total words in Col D
ColDTotalWordCount = Application.WorksheetFunction.CountA(.Columns(4))
'~~> Calculate Percentage
PercentageWord = WordCount / ColDTotalWordCount
GetPercentage = Format(PercentageWord, "00.00%")
End With
End Function

Related

Not able to get around object not set error with exceptions

I am at an impasse figuring out how to catch this null range variable exception.
I am attempting to scan for a row of headers to recover data from a few rows under, the excel datasheets may have multiple "pages" with a new header and date on the next "page" if there happens to be data to fill it and this can extend to many pages.
My loop appears to break on the second pass after the find function is unable to find additional rows with the desired header. My if statement is not able to detect that the variable is blank and I get an object not set error repeatedly.
I have tried several ways at calling null exceptions such as is empty, is null, both in a few different syntax forms, but still no success.
Thanks in advance for your help!
Sub testingBreak()
Dim testing As String
Dim starting As String
testing = "testing"
starting = "starting"
Dim productNameRange() As Range
Dim PN2CellAddress As String
Dim rowCount As Integer
rowCount = 0
Dim oldCount As Integer
oldCount = 0
ReDim productNameRange(rowCount)
Dim r As Integer
Set productNameRange(rowCount) = Sheets(starting).Cells.Find( _
What:="Product Name", LookIn:=xlValues, LookAt:=xlWhole, _
SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=True)
If productNameRange(rowCount) Is Nothing Then
MsgBox ("Search Error: Header Not found")
Else
Do While Not IsEmpty(productNameRange(rowCount)) 'this is to search for additional rows with the same header name
oldCount = rowCount
rowCount = rowCount + 1
MsgBox rowCount & " & " & oldCount
ReDim Preserve productNameRange(rowCount)
If IsNull(productNameRange(oldCount)) Then '<<<<this if statement does not catch that the variable was not set :( <<<<<
MsgBox "null exception worked"
Else
MsgBox productNameRange(oldCount) '<<<<on second loop, I get the error "object varriable or with block varriable not set"... <<<<<<
End If
Set productNameRange(rowCount) = Sheets(starting).Range(productNameRange(oldCount).Address).FindNext( _
productNameRange(oldCount)) ' <<< does not set the next range if there is none
Loop
MsgBox rowCount & "Row(s) have been found!"
For r = 0 To rowCount - 1
MsgBox productNameRange(r)
Next r
End If
End Sub
So this seemed to fix my issue. Thank you to everyone for your help
Dim f As Variant
Private Function FindAllHeaderRows(val As String, filePath As String) As Collection
Dim rv As New Collection, g As Range
Dim addr As String
Dim wb As Workbook: Set wb = Workbooks.Open(filePath) ' workbook containing this code
Dim ws As Worksheet: Set ws = wb.Worksheets("Sheet1")
Set g = ws.Cells.Find(What:=val, LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=True)
If Not g Is Nothing Then addr = g.Address
Do Until g Is Nothing
rv.Add g
Set g = ws.Cells.FindNext(After:=g)
If Not g Is Nothing Then
If g.Address = addr Then Exit Do
End If
Loop
Set FindAllHeaderRows = rv
End Function 'working!
Sub testSub1()
Dim FileToOpen As String
FileToOpen = Application.GetOpenFilename(Title:="Select Data file")
Set rangeCo = FindAllHeaderRows("Product Name", FileToOpen)
For Each f In rangeCo
MsgBox f.Address 'shows address
Next f
MsgBox rangeCo.count ' shows how many
End Sub
Find Criteria Cells (Find & FindNext)
Sub FindCriteriaCells()
Const wsName As String = "Starting"
Const Criteria As String = "Product Name"
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim ws As Worksheet: Set ws = wb.Worksheets(wsName)
Dim rg As Range: Set rg = ws.UsedRange
Dim fCell As Range: Set fCell = rg.Find(What:=Criteria, _
After:=rg.Cells(rg.Rows.Count, rg.Columns.Count), LookIn:=xlFormulas, _
LookAt:=xlWhole, SearchOrder:=xlByRows, MatchCase:=True)
Dim Headers() As Range
Dim n As Long
If Not fCell Is Nothing Then
Dim FirstAddress As String: FirstAddress = fCell.Address
Do
ReDim Preserve Headers(0 To n)
Set Headers(n) = fCell
n = n + 1
Set fCell = rg.FindNext(After:=fCell)
Loop Until fCell.Address = FirstAddress
End If
Dim Msg As String
If n > 0 Then
Msg = "The header '" & Criteria & "' was found in " _
& n & " cell(s):" & vbLf
For n = 0 To n - 1
Msg = Msg & vbLf & Headers(n).Address(0, 0)
Next n
MsgBox Msg, vbInformation
Else
Msg = "The header '" & Criteria & "' was not found."
MsgBox Msg, vbExclamation
End If
End Sub

VBA - Excel insert row above for each cell containing certain text

How do you go through the specific worksheet and in a specific column for every row that contains word "firewall" - then insert an empty row above? The Row with "firewall" may be followed by rows that contain other values. The last line in the column is always "Grand Total". I supposed can be used as condition to stop the loop.
I found on Stack Overflow this example which is almost exactly what I need, but it does it only once, and I need through the entire column for all matches. The worksheet should be specified.
Sub NewRowInsert()
Dim SearchText As String
Dim GCell As Range
SearchText = "Original"
Set GCell = Worksheets("Sheet2").Cells.Find(SearchText).Offset(1)
GCell.EntireRow.Insert
End Sub
My data example:
firewall abc
policy x
policy y
firewall xyz
policy z
policy xxx
Grand Total
Insert Rows (Find feat. Union)
Option Explicit
Sub NewRowInsert()
Const sText As String = "FirEWaLL"
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim ws As Worksheet: Set ws = wb.Worksheets("Sheet1")
Dim LastRow As Long: LastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
Dim rg As Range: Set rg = ws.Range("A2:A" & LastRow)
Dim sCell As Range: Set sCell = rg.Find(sText, , xlFormulas, xlPart)
Application.ScreenUpdating = False
Dim trg As Range
Dim sCount As Long
If Not sCell Is Nothing Then
Dim FirstAddress As String: FirstAddress = sCell.Address
Do
If trg Is Nothing Then
Set trg = sCell
Else
Set trg = Union(trg, sCell.Offset(, sCount Mod 2))
End If
sCount = sCount + 1
Set sCell = rg.FindNext(sCell)
Loop Until sCell.Address = FirstAddress
trg.EntireRow.Insert
End If
Application.ScreenUpdating = True
Select Case sCount
Case 0
MsgBox "'" & sText & "' not found.", vbExclamation, "Fail?"
Case 1
MsgBox "Found 1 occurrence of '" & sText & "'.", _
vbInformation, "Success"
Case Else
MsgBox "Found " & sCount & " occurrences of '" & sText & "'.", _
vbInformation, "Success"
End Select
End Sub

How to search for a string across all the sheets faster in VBA?

I am tryng the search for a string across all sheets, the code below gets a string from each row in a column in one sheet and finds in another worksheet and then gets the formating of the corresponding cell for month.
The issue here is that it is very slow. How can I do this faster? is there a better way?
Sub colorstatus()
Application.ScreenUpdating = False
Range("H1").Activate
Dim c As Range
'//loop it
For Each c In Range(Range("H2"), Range("H2").End(xlDown))
est1 = Split(c, "_")(0) & "_" & Split(c, "_")(1)
ActiveWindow.ActivatePrevious
Dim ws As Worksheet
Dim ws1 As Worksheet
Dim est As Range
Dim strName As String
Dim status As Range
For Each ws1 In Worksheets
Columns.EntireColumn.Hidden = False
Rows.EntireRow.Hidden = False
Next
On Error Resume Next
strName = est1
For Each ws In Worksheets
With ws.UsedRange
Set est = .Find(What:="*" & strName & "*", After:=.Cells(1, 1), LookIn:=xlValues, LookAt:=xlWhole)
If Not est Is Nothing Then
ws.Activate
GoTo 0
End If
End With
Next ws
0
est.Activate
Set status = Cells.Find(What:="*May*", After:=Range("A1"), LookIn:=xlValues, LookAt:= _
xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False _
, SearchFormat:=False)
Range(Split(status.Address, "$")(1) & est.row).Copy
ActiveWindow.ActivatePrevious
c.Offset(0, 11).PasteSpecial Paste:=xlPasteFormats
Next
End Sub
The below code loop all sheets and generate a message box with all sheets names have the value in. You can modify and try:
Sub Macro1()
Dim strSearch As String, strResults As String
Dim rngFound As Range
Dim ws As Worksheet
strSearch = "Test"
strResults = ""
For Each ws In ThisWorkbook.Worksheets
With ws
Set rngFound = .Cells.Find(strSearch, LookIn:=xlValues, Lookat:=xlWhole)
If Not rngFound Is Nothing Then
If strResults = "" Then
strResults = "Searching value, " & strSearch & ", appears in " & ws.Name
Else
strResults = strResults & ", " & ws.Name
End If
End If
End With
Next ws
If strResults <> "" Then
MsgBox strResults & "."
End If
End Sub
This piece of code will end either a message with the address for the cell which the word was found, or a message telling you that it didn't found the word:
Option Explicit
Sub colorstatus()
Application.ScreenUpdating = False
Dim ws As Worksheet
Dim cell As Range
Dim TheWord As String: TheWord = "dog_390"
For Each ws In ThisWorkbook.Sheets
Set cell = ws.Range("A:A").Find(TheWord, LookAt:=xlPart)
If Not cell Is Nothing Then
MsgBox "Word " & TheWord & "found in cell: " & cell.Address & " in worksheet: " & ws.Name
End
End If
Next ws
MsgBox "Word " & TheWord & " was not found on this workbook."
End Sub
Try the next code, please:
Sub colorstatus()
Dim sh As Worksheet, celFound As Range, strWord As String
Dim status As Range
strWord = "dog_390"
For Each sh In ActiveWorkbook.Sheets
Set celFound = sh.Range("A:A").Find(strWord, LookAt:=xlPart)
If Not celFound Is Nothing Then
Set status = sh.Rows(1).Find(What:="May", After:=sh.Range("A1"), LookAt:=xlPart)
If Not status Is Nothing Then
Debug.Print sh.Name, sh.cells(celFound.Row, status.Column).Interior.Color, sh.cells(celFound.Row, status.Column).Address
'do whatever you need with the found cell...
'....
Else
Debug.Print sh.Name, "No month found"
End If
Else
Debug.Print sh.Name, "No match found"
End If
Next sh
End Sub

How to Find specific text word using Excel vba

I need to find a specific word from an Excel file. I want to search row by row, and if the word is found, skip 2 rows down and copy the next 20 rows and loop to the next word.
Sub Example4()
Dim FilePath As Workbook
Dim wsheet As Worksheet
Dim i, lcount, lcount2 As Integer
Dim cell, rgFound As Range
Dim Found As Range, LastRow As Long
Set FilePath = Workbooks.Open("D:\SLC.txt")
Dim rowVal As Integer
rowVal = 1
For lcount = 1 To FilePath.Sheets("SLC").Range("A1048576").End(xlUp).Row
Set rgFound = Range("A1:A1048576").Find("TXN. NO TXN SEQ", ThisWorkbook.Sheets(), Cells(rowVal, 1))
FilePath.Cells(wsheet.Range(rowVal).End(xlDown).Row + 3).xlCopy
wbook2.Worksheets(1).Range("A1").PasteSpecial xlPasteValuesAndNumberFormats
wbook2.SaveAs ("D:\SLC_Copied.xlsx")
wbook2.Close
rowVal = rgFound1.Row
Debug.Print lcount
Next lcount
End Sub
As Siddharth Rout suggested, use Find and FindNext.
Try to choose variable names appropriate to their type, calling a workbook object FilePath is confusing to others trying to understand your script.
Option Explicit
Sub Example4()
Const TEXT = "TXN. NO TXN SEQ"
Const TEXT_FILENAME = "D:\SLC.txt"
Const OUT_FILENAME = "D:\SLC_Copied.xlsx"
Dim wbText As Workbook, wbOut As Workbook, rngOut As Range
Dim wsText As Worksheet, wsOut As Worksheet, count As Integer
Dim rngSearch As Range, rngFound As Range, rowFirstFind As Long
' open text file no link update, read only
Set wbText = Workbooks.Open(TEXT_FILENAME, False, True)
Set wsText = wbText.Sheets(1)
' search
Set rngSearch = wsText.Columns("A:A")
Set rngFound = rngSearch.Find(what:=TEXT, LookIn:=xlValues, LookAt:=xlPart)
If rngFound Is Nothing Then
wbText.Close
MsgBox "No lines match [" & TEXT & "]", vbCritical, "Exiting Sub"
Exit Sub
Else
' create new workbook for results
Set wbOut = Workbooks.Add
Set wsOut = wbOut.Sheets(1)
Set rngOut = wsOut.Range("A1")
rowFirstFind = rngFound.Row
Do
'Debug.Print rngFound.Row
rngFound.Offset(3, 0).Resize(20, 1).Copy rngOut
Set rngOut = rngOut.Offset(20, 0)
Set rngFound = rngSearch.FindNext(rngFound)
count = count + 1
Loop Until rngFound.Row = rowFirstFind
End If
wbText.Close False
wbOut.SaveAs OUT_FILENAME
MsgBox count & " blocks copied to " & wbOut.Name, vbInformation, "Finished"
wbOut.Close
End Sub

check every cell in a range for a specific string?

I want a VBA code by which I can check every cell in a range with a specific text?
EG: for each cell in range (a:a)
if value of cell = "specific text"
do this
else
do that
*
How to do this in VBA Excel?
here you go, but please try to find on google first
Sub eachCell()
Dim c As Range
For Each c In Range("A1:D21")
If (c.Value = "mytext") Then 'if value of cell = "specific text"
c.Value = "other text" 'do this
Else
c.Value = "other text 2" 'do that
End If
Next c
End Sub
Using a Find loop will be quicker than looking at each cell
Sub Sample_Find()
Dim rng1 As Range
Dim rng2 As Range
Dim bCell As Range
Dim ws As Worksheet
Dim SearchString As String
Dim FoundAt As String
Set ws = Worksheets(1)
Set rng1 = ws.Columns(1)
SearchString = "specific text"
Set rng2 = rng1.Find(SearchString, , xlValues, xlWhole)
If Not rng2 Is Nothing Then
Set bCell = rng2
FoundAt = rng2.Address
MsgBox "do something here " & FoundAt
Do
Set rng2 = rng1.FindNext(After:=rng2)
If Not rng2 Is Nothing Then
If rng2.Address = bCell.Address Then Exit Do
FoundAt = FoundAt & ", " & rng2.Address
MsgBox "do something here " & rng2.Address
Else
Exit Do
End If
Loop
Else
MsgBox SearchString & " not Found"
Exit Sub
End If
MsgBox "The Search String has been found these locations: " & FoundAt
Exit Sub
End Sub
Another option to answer your post, using the AutoFilter.
Code
Option Explicit
Sub Test_AutoFilter()
Dim ws As Worksheet
Dim SearchString As String
Dim Rng As Range
Dim VisRng As Range
Dim c As Range
Set ws = Worksheets(1)
Set Rng = ws.Columns(1)
SearchString = "specific text"
Rng.AutoFilter
Rng.AutoFilter Field:=1, Criteria1:=SearchString
' set another range to only visible cells after the Filter was applied
Set VisRng = ws.Range(Cells(1, 1), Cells(1, 1).End(xlDown)).SpecialCells(xlCellTypeVisible)
If Not VisRng Is Nothing Then
' Option 1: show every cell that a SearchString was found
For Each c In VisRng
MsgBox "String match of " & SearchString & " found as cell " & c.Address
Next c
' Option 2: show all the cells that SearchString was found (in 1 message)
MsgBox "String match of " & SearchString & " found as cells " & VisRng.Address
End If
End Sub

Resources