Targetting a Range With Dynamic Row Reference Based On Search - vba

I'm real new to VBA coding and have been doing alright but I have now hit a wall with my final (and probably more complex than it needs to be) macro of the worksheet. I've been trying to make it work all weekend through multiple google searches and using various answers from stackoverflow's other questions to compile my own script, but to no avail. This is what I have so far (apologies coders, I know this will look like it was written by a 3 year-old):
Sub Build_Delete()
Dim rngA As Range
Dim cell As Range
Set rngA = Worksheets("Database").Range("D9:D177").End(xlUp)
For Each cell In rngA
If cell.Value = Range("A2").Value Then
cell.Select
Range("D" & ActiveCell.Row & ":AB" & ActiveCell.Row).Select
Selection.Delete
End If
Next cell
End Sub
The above works, no errors are returned, however it doesn't do anything noticeable.
I'm aware this is most likely atrocious, so this is what I am trying to do:
Database!D9:D177 contains the titles for a set of data in columns D to AB (4 to 28) .
There is an ActiveX Search Box that populates cell Database!A2 in real time with whatever is searched (eg. "Test" typed into Search Box, "Test" appears in cell Database!A2).
When I run the macro, I want it to check range Database!D9:D177 for the text string found in Database!A2, then delete the contents of columns D to AB for that row (eg. A2 = "test", Found "test" in cell D21, Delete D21:AB21).
The row is a dynamic value which is what is throwing me mostly with this, but the columns are fixed.
Also, the button for the macro is located on a separate worksheet (Front Page!), but the script will run solely on the Database! page.
Only needs to work in excel, not open office.
Only other thing I can think of that is relevant is that the cells can be left blank after deletion, they do not need to be filled, and the worksheet will never need to be printed so margins aren't an issue.
Optionally I would like to add an "Are You Sure? 'Yes' 'No' Msgbox at the start of the script, but I can play with that later as I know I am pushing my luck with this.
Any help would be greatly appreciated!

I always find it faster to use FIND rather than check the value of each cell.
If you want to find all values in case of duplicates you can go on to use .FINDNEXT(rFound) - https://msdn.microsoft.com/en-us/library/office/ff839746.aspx
Public Sub Build_Delete()
Dim rngA As Range
Dim rFound As Range
Dim wrkSht As Worksheet
Set wrkSht = ThisWorkbook.Worksheets("Database")
Set rngA = wrkSht.Range("D9:D177")
With rngA
Set rFound = .Find(wrkSht.Range("A2"), LookIn:=xlValues, LookAt:=xlWhole)
If Not rFound Is Nothing Then
If MsgBox(rFound.Value & " found on row " & rFound.Row & "." & vbCr & _
"Delete?", vbInformation + vbYesNo) = vbYes Then
rFound.EntireRow.Delete Shift:=xlUp
End If
End If
End With
End Sub

Related

VBA set cell value after .ClearContents

Why does the cell value not set in another function when clearing the contents of the range in another function?
I'm trying to set a cell value to "All" after clearing the cells in the range. I've even tried to get a message box to pop up to see if i can somehow check if my check value is correct.
DelRange is the range i'm clearing.
Building is the cell that i'm checking the value for and if it's blank, it needs to change to "All".
clearPreviw is used to clear another sheet, which it's doing.
Sub ClearSheet()
Dim Dash As Worksheet
Dim DelRange As Range
Dim Building As Range
Set Dash = ActiveWorkbook.Worksheets("DASH")
Set DelRange = Dash.Range("FilterData")
Set Building = Dash.Range("SelBuild")
DelRange.ClearContents
Call clearPreview
'This part below doesn't work when the Range.ClearContents has been done, but doing it on it's own without clearing the range works fine
If Building.Value = "" Then
MsgBox "Building is empty", vbOKOnly
Building.Value = "All"
End If
End Sub
I've run this test as a separate process which works, but once again when running it as a call function right after .ClearContents seems to stop this.
Sub test()
Dim Dash As Worksheet
Dim DelRange As Range
Dim Building As Range
Set Dash = ActiveWorkbook.Worksheets("DASH")
Set DelRange = Dash.Range("FilterData")
Set Building = Dash.Range("SelBuild")
If Building.Value = "" Then
MsgBox "Building is empty", vbOKOnly
Building.Value = "All"
End If
End Sub
I've been poking at it and searching but i can't wrap my head around this.
I think you are missing:
Building.ClearContents;
Also I would prefer:
If IsEmpty(Building.Value) Then
over:
If Building.Value = "" Then
This link gives you a good start on how to set range variables (although I would advice you against the use of .Select and .Activate).
After that, use .ClearContents or .Clear, depending on your needs.
If you properly cleared the ranges, there is no need to check if they are empty, so this might be a redundant step within your current planning.

Wait for external data to load before automatic calculations? Excel/VBA

First time poster, been searching for a solution to this all over but no luck yet.
To explain my problem:
TERMS:
OPC = Object Linking and Embedding (OLE) for Process Control
(allows other applications to use data from PLC tags)
PLC = Programmable Logic Controller (computer for process control
SCADA = Supervisory Control And Data Acquisition (interface that displays values from PLC and allows control)
I have an excel workbook which is automatically opened by the SCADA system (WonderWare > Intouch, the software) at a specific time after the PLC has sorted some values. This workbook populates its cells using the OPC client, accessing them using this method:
=OPCLINK|EAST!'r[BELLWWPOWER]DailyValues_Z3[1,21]'
This works well but there are a lot of cells to populate so it takes a few seconds.
What I want to automatically happen is for these cells to populate and any calculations to complete before all the cells with formulas are changed to just the values of those formulas. The workbook is then saved under a new workbook name ("PowerReports-YesterdaysDate") with the VBA code stripped and both workbooks are closed (without saving the original, to preserve formulas).
This all works well except it happens too fast and the new saved copy ends up having just "#N/A" in all the cells with OPC links. When I had the first sheet's private sub as "Worksheet_Activate()" instead of "Worksheet_Calculate()", the code wouldn't stat automatically and waited for a mouse click onto one of the sheet's cells (FYI: the SCADA system opens this workbook to sheet 1 automatically to start with sheet 1's code). The new copy would save successfully in this case, but when the code stats automatically it is too fast. How can I wait for the external data to load before the calculations are done?
I've tried things (I don't know how successfully they were implemented..) like:
-Application.Calculate
-Application.RefreshAll
-Timers
-Trying to get a flag from the PLC
-Checking for remaining #N/As
It seems like if a loop or something similar is running right away it doesn't let the external data refresh.
Private Sub Worksheet_Calculate()
' When first sheet "Main" is activated, all formulas are replaced
' with their calculated values. The second sheet, "Monthly Values" is then activated
Dim rng As Range, r As Range
Set rng = Range("A1:D52")
For Each r In rng
If r.HasFormula Then
r.Value = r.Value
End If
Next r
Worksheets("Monthly Data").Activate
End Sub
Private Sub Worksheet_Activate()
' When second sheet "Monthly Values" is activated, all formulas are replaced
' with their calculated values. The sub routine, "SaveWithoutMacros" is then called
Dim rng As Range, r As Range
Set rng = Range("A1:BJ84")
'Worksheets("Monthly Data").Calculate
'If Not Application.CalculationState = xlDone Then
'DoEvents
'End If
For Each r In rng
If r.HasFormula Then
r.Value = r.Value
End If
Next r
Call SaveWithoutMacros
End Sub
Sub SaveWithoutMacros()
'Purpose : To save a copy of the active workbook without macros
Dim vFilename As String
Dim wbActiveBook As Workbook
'----------------------------------------------------------------------
'Following two lines causes an error in Excel 97 - comment them out
Dim VBComp As VBIDE.VBComponent
Dim VBComps As VBIDE.VBComponents
'----------------------------------------------------------------------
' Save to filename in format (yesterdays date) "PowerReports-DD-MM-YYYY"
vFilename = ("D:\PowerReports\" & "PowerReport-" _
& Format(Date - 1, "DD-MMM-YYYY") & ".xls")
ActiveWorkbook.SaveCopyAs vFilename
Set wbActiveBook = Workbooks.Open(vFilename)
'Now strip all VBA, modules, userforms from the copy
'This code is from Chip Pearson's website http://www.cpearson.com
Set VBComps = wbActiveBook.VBProject.VBComponents
For Each VBComp In VBComps
Select Case VBComp.Type
Case vbext_ct_StdModule, vbext_ct_MSForm, vbext_ct_ClassModule
VBComps.Remove VBComp
Case Else
With VBComp.CodeModule
.DeleteLines 1, .CountOfLines
End With
End Select
Next VBComp
wbActiveBook.Save ' saves new version after code is stripped
ThisWorkbook.Saved = True ' sets save flag to true, does not actually save
Application.Quit ' quits entire application, all workbooks
End Sub
Sorry for the lengthy post, saw other people getting ripped on for not being detailed enough, haha.
This should work for you now , by testing only the last cell being filled in then you will be sure all the data is in before you change them to values
Were basically telling worksheet_calculate to do nothing until the last cell has a formula
NOTE : SEE OP ANSWER BELOW FOR MODIFIED CODE THAT WORKED IN THIS SCADA SITUATION
Private Sub Worksheet_Calculate()
Dim rngLastCell As Range
Set rngLastCell = Range("D52")
If rngLastCell.HasFormula Then
Dim rng As Range, r As Range
Set rng = Range("A1:D52")
For Each r In rng
If r.HasFormula Then
r.Value = r.Value
End If
Next r
Worksheets("Monthly Data").Activate
End If
End Sub
Ended up getting it! Thanks to Steven Martin for giving me a jump off point to get this working, until you you posted your answer I didn't think an if statement would work for me here without a loop.
This is what worked for me:
Private Sub Worksheet_Calculate()
Dim rngLastCell As Range
Set rngLastCell = Range("D52")
If WorksheetFunction.IsNA(rngLastCell) = False Then
Dim rng As Range, r As Range
Set rng = Range("A1:D52")
For Each r In rng
If r.HasFormula Then
r.Value = r.Value
End If
Next r
Worksheets("Monthly Data").Activate
End If
End Sub
And then the same IF statement checking for "#N/A" in the 2nd sheet's code too, works like a charm now.

Start VBA macro when editing a cell

I simply try to write a search macro in an excel sheet. How can I start a macro dynamically DURING editing a cell. When writing in a cell the search macro should run in the background with every character added or deleted not just at the end.
Worksheet_Change(ByVal Target As Range) only starts when editing is finished (return was hit or other cell was selected).
Thanks.
You can't. The code engine won't run while Excel is in Edit mode. You have to have the user enter the text in something other than a cell - like a control on the worksheet or a control on a userform.
Thanks to Dick Kusleika for answering my question and to put me on the right track.
Here is the final solution for anybody having similar demands. It basically works with an ActiveX TextBox to enter the search-string. The macro than is looking in the search-area for all entries containing the search-string. All other filled rows within the search-field will get hidden. This works right away when writing into the TextBox. So, when deleting characters in the search-string the once hidden rows will appear right away if appropriate.
Private Sub TextBox1_Change()
Dim searchArea As Range, searchRow As Range, searchCell As Range
Dim searchString As String
Dim lastRow As Integer
Application.ScreenUpdating = False
searchString = "*" & LCase(TextBox1.Value) & "*"
' unhide rows to have the full search field when editing
Rows.Hidden = False
lastRow = ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Row
Set searchArea = Me.Range("A5", "A" & lastRow) 'Me.Range("A5").End(xlDown))
searchArea.EntireRow.Hidden = True
For Each searchRow In searchArea.Rows
For Each searchCell In searchRow.Cells
If LCase(searchCell) Like searchString Then
searchRow.Hidden = False
Exit For
End If
Next searchCell
Next searchRow
Application.Goto Cells(1), True
Application.ScreenUpdating = True
End Sub
works like a charm.

Excel 2010 VBA How to lookup a value in multiple sheets?

I have an excel file with 14 worksheets, i need to lookup for a value in different columns of each sheet, and if its found, return the name of the sheet where the value was found in a list on a summary sheet.
I have tried with if and vlookup function but i can´t find a proper result, also i tried with pivot table but since i have multiple sheets its not working for me.
I am hoping that somebody helps me with a bit of VBA coding to solve this issue.
I am very newbie at coding and VBA and still i don´t understand all of it, so i haven´t tried to code myself, sorry for that.
Try using the following formula functions to create a solution. If you can't come up with something that works, post what you have and we can work through it.
ADDRESS(row_num, column_num, [abs_num], [a1], [sheet_text])
VLOOKUP(lookup_value,table_array,col_index_num,range_lookup)
IF(logical_test,value_if_true,value_if_false)
Also consider using Named Ranges
Let me know what you come up with :)
Hope this helps. :)
Sub findStuff()
Dim ws As Worksheet
Dim strWhat As String
Dim rngSearch As Range
Dim rngFound As String
Dim i As Integer
strWhat = "Raspberry"
For Each ws In Worksheets
Set rngSearch = ws.Cells.Find(What:=strWhat)
If Not rngSearch Is Nothing Then
i = i + 1
If i = 1 Then
rngFound = rngSearch.Worksheet.Name
Else
rngFound = rngFound & ", " & rngSearch.Worksheet.Name
End If
End If
Next ws
MsgBox "'" & strWhat & "' found on the following worksheet(s): " & rngFound & "."
End Sub

Finding a specific keyword in many workbooks along with a corresponding value and placing them in a column in one workbook

In a previous posting I asked about how to highlight a cell range that began with a certain keyphrase and ended when the next cell was blank. I would like to gain a better understanding of how to create a loop that performs this on multiple Excel files. Any help would be much appreciated. For reference, the code I am referring to is as follows:
Dim wk As Worksheet
Set wk = ActiveSheet
FirstRowColA = Application.WorksheetFunction.Match("keyphrase", wk.[A:A])
LastRowColA = Cells(wk.Rows.Count, "A").End(xlUp).Row
wk.Range("A" & FirstRowColA & ":A" & LastRowColA).Copy
Worksheets("Sheet2").Paste
In addition, I was curious about how to handle creating a "Sheet 2" if one does not exist already in the active workbook. Do I need to use something like Set WS = Sheets.Add and have Excel look at Worksheets(Sheets.Add).Paste?
I have also noticed that this code does not necessarily find what I am telling it to find, but this is an issue I should be able to resolve. For example, putting the phrase "Name" in the Match() function returns the text of a cell in column A containing a different word.
Let say u have excel files in the some folder
this code opens each workbook in the folder and searches specific string if found .copy and paste the required data.
Sub LoopThroughFiles()
Dim StrFile As String
Dim wk As Worksheet
StrFile = Dir("C:\Personal\Excel Report\*.xlsx")
Do While Len(StrFile) > 0
Workbooks.Open ("C:\Personal\Excel Report\" & StrFile)
Set wk = ActiveSheet
Set firstrowcola = activesheet.Range("A:A").Find("taskname") ' - search taskname in 1st row
If firstrowcola Is Nothing Then GoTo here:
LastRowColA = Cells(wk.Rows.Count, "A").End(xlUp).Row
wk.Range(firstrowcola.address & ":" & firstrowcola.offset(lastrowcola,0).address)).Copy
Set ws = Sheets.Add
ws.Range("A1").Select
ActiveSheet.Paste
here:
ActiveWorkbook.Close True
Loop
End Sub