Insert a row in a data table at a special position under conditions - excel

I've been working on the development of a tool that is supposed to help me manage some projects.
I have a table of data called t_data.
This data table contains every projects. Each project is devided on quarters (Q1 2019, Q2 2019, Q3 2019, etc.). Each quarter is devided on deliverables (not always the same number of deliverables so not the same amount of rows for each quarter).
I have a form in another sheet (name of the sheet: MENU!) that permits to add a new deliverable to a Quarter of a project, and where I put the necessary inputs so that I can find the good raw where I should insert my deliverable. The inputs are the project's name (in MENU!D10) and the quarter concerned by the deliverable (in MENU!D12).
Here is my code :
Sub ajouter_un_livrable()
'
' ajouter_un_livrable Macro
' Ajoute un livrable en fonction de son challenge et de son trimestre.
'
Dim result As Variant
match_formula = "EQUIV(1;(t_data[Associated_challenge] = MENU!$D$10)*(t_data[Associated_quarter] = MENU!$D$12);0)"
result = Evaluate(match_formula)
numero_ligne = CLng(result)
numero_ligne = numero_ligne - 2003
Worksheets("TRT RTI Challenges").Rows(numero_ligne).insert
'Set datasheet = Worksheets("TRT RTI Challenges").ListObjects("t_data")
'With datasheet
'.Cells(numero_ligne, 10).Select
'Selection.ListObject.ListRows.Add (numero_ligne)
'Set myNewDeliverable = .ListRows.Add(numero_ligne)
'End With
'
End Sub
You'll notice I'm french ehe
numero_ligne sounds to return the number 2015 because I have an error 2015... great !
I don't know how to manage the EVALUATE. How can I take its value into a variable ? I've tried a lot of things, consult a lot of forums but nothing's working :'(
Do you have an idea of how I could solve my issue ?
Thanks a lot to the one or those that will help me or at least try. :D

I believe something like this should work for you:
Sub ajouter_un_livrable()
Dim wsInput As Worksheet
Dim rProjects As Range
Dim rQuarters As Range
Dim rFound As Range
Dim vProject As Variant
Dim vQuarter As Variant
Dim sProjectCell As String
Dim sQuarterCell As String
Dim sFirst As String
Dim bMatch As Boolean
sProjectCell = "D10"
sQuarterCell = "D12"
On Error Resume Next
Set wsInput = ActiveWorkbook.Worksheets("MENU")
Set rProjects = Range("t_Data").ListObject.ListColumns("Associated_challenge").DataBodyRange
Set rQuarters = Range("t_Data").ListObject.ListColumns("Associated_quarter").DataBodyRange
On Error GoTo 0
If wsInput Is Nothing Or rProjects Is Nothing Or rQuarters Is Nothing Then
MsgBox "Unable to find a worksheet named 'MENU' or unable to find a table named 't_Data' in this workbook.", , "Error"
Exit Sub
End If
vProject = wsInput.Range(sProjectCell).Value
vQuarter = wsInput.Range(sQuarterCell).Value
If Len(vProject) = 0 Then
wsInput.Select
wsInput.Range(sProjectCell).Select
MsgBox "Input for Project is required.", , "Error"
Exit Sub
ElseIf Len(vQuarter) = 0 Then
wsInput.Select
wsInput.Range(sQuarterCell).Select
MsgBox "Input for Quarter is required.", , "Error"
Exit Sub 'No data
End If
bMatch = False
Set rFound = rProjects.Find(vProject, rProjects.Cells(rProjects.Cells.Count), xlValues, xlWhole, , xlNext, False)
If Not rFound Is Nothing Then
sFirst = rFound.Address
Do
If LCase(rQuarters.Worksheet.Cells(rFound.Row, rQuarters.Column).Value) = LCase(vQuarter) Then
bMatch = True
Exit Do
End If
Set rFound = rProjects.FindNext(rFound)
Loop While rFound.Address <> sFirst
If bMatch Then
rFound.EntireRow.Insert
'Row inserted, proceed with what you want to do with the inserted row here
End If
Else
MsgBox "Unable to find matching row for :" & Chr(10) & "Project: " & vProject & Chr(10) & "Quarter: " & vQuarter, , "Error"
End If
End Sub

Related

method find of object range failed in vba

I have written a code that finds all the dye word and sum all the dye word value.
Here is the code
Dim name As String
name = "dye"
Dim findDyeRange As Range
Set findDyeRange = Range("Q10:S61")
Set firstDyeWord = findDyeRange.Find(name)
If firstDyeWord Is Nothing Then
msgbox "nothing found"
Else
firstDyeValue = firstDyeWord.Offset(0, 1).Value
Set secondDyeWord = findDyeRange.FindNext(firstDyeWord)
If secondDyeWord.Address = firstDyeWord.Address Then
MsgBox firstDyeValue
Exit Sub
Else
secondDyeValue = secondDyeWord.Offset(0, 1).Value
Set thirdDyeWord = findDyeRange.FindNext(secondDyeWord)
If thirdDyeWord.Address = firstDyeWord.Address Then
MsgBox firstDyeValue + secondDyeValue
Exit Sub
Else
thirdDyeValue = thirdDyeWord.Offset(0, 1).Value
Set fourthDyeWord = findDyeRange.FindNext(thirdDyeWord)
If fourthDyeWord.Address = firstDyeWord.Address Then
MsgBox firstDyeValue + secondDyeValue + thirdDyeValue
Exit Sub
Else
fourthDyeValue = fourthDyeWord.Offset(0, 1).Value
Set fifthDyeWord = findDyeRange.FindNext(fourthDyeWord)
If fifthDyeWord.Address = firstDyeWord.Address Then
MsgBox firstDyeValue + secondDyeValue + thirdDyeValue + fourthDyeValue
Exit Sub
Else
fifthDyeValue = fifthDyeWord.Offset(0, 1).Value
Set sixthDyeWord = findDyeRange.FindNext(fifthDyeWord)
If sixthDyeWord.Address = firstDyeWord.Address Then
MsgBox firstDyeValue + secondDyeValue + thirdDyeValue + fourthDyeValue + fifthDyeValue
Exit Sub
Else
sixthDyeValue = sixthDyeWord.Offset(0, 1).Value
MsgBox firstDyeValue + secondDyeValue + thirdDyeValue + fourthDyeValue + fifthDyeValue + sixthDyeValue
End If
End If
End If
End If
End If
End If
the code runs well. But when I removes the msgbox and set a code then it throws an error.
I want this code
If firstDyeWord Is Nothing Then
Range("A9").value = 7
But it throws error "method find of object range failed in vba"
Help Please!
According to the documentation of the Range.Find method you must at least specify the parameters LookIn, LookAt, SearchOrder and MatchByte when using Find() otherwise it uses what ever was used last by either VBA or the user interface.
Since you cannot know what your users used last in the user interface your search might randomly work and randomly come up with wrong results. Therefore always specify all of these 4 parameters to make it reliable.
Additionally you must specify in which workbook/worksheet your ranges are. Otherwise Excel guesses and it might guess the wrong sheet.
Make sure to declare all your variables properly. I recommend always to activate Option Explicit: In the VBA editor go to Tools › Options › Require Variable Declaration.
Public Sub Example()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet1") 'set your workbook and worksheet!
Dim name As String
name = "dye"
Dim findDyeRange As Range
Set findDyeRange = ws.Range("Q10:S61") 'specify in which sheet the range is
Dim firstDyeWord As Range
Set firstDyeWord = findDyeRange.Find(What:=name, LookIn:=xlFormulas, LookAt:=xlWhole, SearchOrder:=xlByRows, MatchByte=False)
If firstDyeWord Is Nothing Then
'dye was NOT found
ws.Range("A9").Value = 7 'specify in which sheet the range is
Else
'do something else if dye was found
End If
End Sub
// Edit (see comment)
If this is used in an event like Worksheet_Change you need to turn off events before writing to a cell. Otherwise this will trigger another event which will trigger another event … and you get stuck in an endless loop of events, which cannot work:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet1") 'set your workbook and worksheet!
Dim name As String
name = "dye"
Dim findDyeRange As Range
Set findDyeRange = ws.Range("Q10:S61") 'specify in which sheet the range is
Dim firstDyeWord As Range
Set firstDyeWord = findDyeRange.Find(What:=name, LookIn:=xlFormulas, LookAt:=xlWhole, SearchOrder:=xlByRows, MatchByte=False)
If firstDyeWord Is Nothing Then
'dye was NOT found
On Error Goto REACTIVATE_EVENTS 'in any case of error reactivate events
Application.EnableEvents = False 'disable events or .Value = 7 triggers another change event.
ws.Range("A9").Value = 7 'specify in which sheet the range is
Application.EnableEvents = True 'make sure you never leave events disabled otherwise they will stay off until you restart Excel.
Else
'do something else if dye was found
End If
Exit Sub
REACTIVATE_EVENTS:
Application.EnableEvents = True
If Err.Number <> 0 Then Err.Raise Err.Number, Err.Source, Err.Description, Err.HelpFile, Err.HelpContext 'show error message if there was an error.
End Sub

Excel VBA - Range(Find().Adress).Row

I have googled and struggled with this for hours now.
I have a Control workbook, that pulls data from a varied amount of other workbooks (the Control workbook also creates the other workbooks and saves the names and dir of said workbooks so that they can be called later)
This piece of code is the problem.
Application.DisplayAlerts = False
Application.ScreenUpdating = False
Declare_Sheets
Dim SearchresultROW
Dim Searchresult As String
Dim complexrow As Integer
Dim CurrSheet As Worksheet
Dim Stype As String
Dim startROW As Integer
Dim endROW As Integer, SearchCOL As Integer, OffROW As Integer
Dim PDATArange As Range, CDATArange As Range
Dim Dateyear, Datemonth, datetest As String
Stype = WSRD.Range("B11")
'Find complex to work with
complexrow = WSSS.Range("F7")
WSSS.Activate
SearchresultROW = Range(Cells(7, 15), Cells(complexrow, 15).Find(Callsheet).Address).Row
Searchresult = WSSS.Cells(SearchresultROW, 15).Offset(0, 1)
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
The below code is the problem extract
complexrow = WSSS.Range("F7")
WSSS.Activate
SearchresultROW = Range(Cells(7, 15), Cells(complexrow, 15).Find(Callsheet).Address).Row
Searchresult = WSSS.Cells(SearchresultROW, 15).Offset(0, 1)
1st problem
I cant get the find() to work without activating worksheet - WSSS
Declare_Sheets gets run at the start which declares WSSS, this works everywhere else in my code, but not with this find().
2nd problem
The code below compiles and finishes, BUT - It does not return the correct data.
This code calls starts the macro
Cancel = True
Dim Calsheet As String
If Target.Column <> 1 Then Exit Sub
Calsheet = Target.Value
Call Call_Readings(Calsheet)
End Sub
There are currently 2 possibilities
I double click on Casper Tcomp 4.
Callsheet = "Casper Tcomp 4" - Which is correct (target of the double click)
Complexrow = "9" - Which is correct (this will increment as new sheets are added)
SearchresultROW = "7" - This is wrong, it should be 8
I have tried adding LookAt:=xlWhole and LookIn:-xlValues, doesnt change a thing
Application.DisplayAlerts = False
Application.ScreenUpdating = False
Declare_Sheets
Dim SearchresultROW
Dim Searchresult As String
Dim complexrow As Integer
Dim CurrSheet As Worksheet
Dim Stype As String
Dim FindResult As Range
Dim startROW As Integer
Dim endROW As Integer, SearchCOL As Integer, OffROW As Integer
Dim PDATArange As Range, CDATArange As Range
Dim Dateyear, Datemonth, datetest As String
Stype = WSRD.Range("B11")
'Find complex to work with
complexrow = WSSS.Range("F7")
On Error Resume Next 'next line will error if nothing is found
Set FindResult = WSSS.Range(WSSS.Cells(7, 15), WSSS.Cells(complexrow, 15)).Find(What:=Callsheet, LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, MatchByte:=False)
On Error GoTo 0 'always re-activate error reporting!
If Not FindResult Is Nothing Then 'check if find was successful
SearchresultROW = FindResult.Row
Searchresult = WSSS.Cells(SearchresultROW, 15).Offset(0, 1)
Else 'if nothing was found show message
MsgBox "NO WB FOUND.", vbCritical
End If
This solved the problem, thanks for the assistance Pᴇʜ
Your code without .Activate would look something like below. Note that every Range, Cells, Rows or Columns object needs to be referenced with the correct Workbook/Worksheet:
complexrow = WSSS.Range("F7")
'try to find something
Dim FindResult As Range
On Error Resume Next 'next line will error if nothing is found
Set FindResult = WSSS.Cells(complexrow, 15).Find(What:=Callsheet, LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, MatchByte:=False)
On Error GoTo 0 'always re-activate error reporting!
If Not FindResult Is Nothing Then 'check if find was successful
SearchresultROW = WSSS.Range(WSSS.Cells(7, 15), FindResult).Row
Searchresult = WSSS.Cells(SearchresultROW, 15).Offset(0, 1)
Else 'if nothing was found show message
MsgBox "nothing found.", vbCritical
End If
Note that if using the Range.Find method you need to check if something was found before you can use the result of Find. Otherwise it will throw an error. Also note that the documentation of Find says that …
The settings for LookIn, LookAt, SearchOrder, and MatchByte are saved each time you use this method.
So if you don't define them each time using Find it will use whatever was used last by either VBA or the user interface. Since you have no control about what was used last by the user interface I highly recomment to define them everytime using Find or you will get random results.
Also note that Callsheet is not defined in your code yet, so check that.

Return to a certain routine when an IF condition is not met

Facing an issue with coming up with a way to send back my code to a certain place when an IF condition is not met. In the code below, I have included an input box requiring data to be entered however through an IF condition I want to make sure atleast 8 digits are entered, If less than 8 digits are entered then I want to show a msg box "Error" and return to GL_Code position asking user to fill the inputbox again.
Dim GL_CY As Variant
Dim GL_Book As Workbook
GL_CY = Application.GetOpenFilename(Title:="Open GL", FileFilter:="Excel Files (*.xls*),*xls*")
Set GL_Book = Application.Workbooks.Open(GL_CY)
'Filtering Range
Dim GL_Code As Variant, GL_Rng As range, GL_LR As Long
Dim GL_Sheet As Worksheet
Set GL_Sheet = GL_Book.Worksheets(1)
GL_LR = GL_Sheet.range("B" & Rows.Count).End(xlUp).Row
GL_Code = Application.InputBox(Prompt:="Enter GL code to generate its activity ", Title:="Generate GL Activity", Type:=1)
If VBA.IsError(GL_Code) Then
GoTo ErrorHandle
ElseIf Len(GL_Code) < 8 Then
MsgBox "GL Code Not Entered", , "Error"
'Return To GL_Code
End If
Set GL_Rng = GL_Sheet.range("A4:R" & GL_LR).CurrentRegion.Offset(3, 0)
Relevant part of the issue is (Need a code for the commented part at the last line)
GL_Code = Application.InputBox(Prompt:="Enter GL code to generate its activity ", Title:="Generate GL Activity", Type:=1)
If VBA.IsError(GL_Code) Then
GoTo ErrorHandle
ElseIf Len(GL_Code) < 8 Then
MsgBox "GL Code Not Entered", , "Error"
'Return To GL_Code
Naqi,
This should do the trick, at least it worked on my machine. I had to put a phony ErrorHandle label in as you didn't show that in your code.
Option Explicit
Sub Test()
Dim GL_Code As String
Dim GoodEntry As Boolean
GoodEntry = False
Do
GL_Code = Application.InputBox(Prompt:="Enter GL code to generate its activity ", Title:="Generate GL Activity", Type:=1)
If (GL_Code = False) Then Exit Sub 'User pressed CANCEL!
If VBA.IsError(GL_Code) Then
GoTo ErrorHandle
Else
If Len(GL_Code) < 8 Then
MsgBox "GL Code Not Entered", , "Error"
'Return To GL_Code
Else
GoodEntry = True
End If
End If
Loop Until GoodEntry
ErrorHandle:
End Sub
HTH

is there a code that can fix my current code?

I've created a check-in / check-out system. my code works perfectly fine when applied to only one sheet. but when I try to apply this code to multiple sheets, I get error, I've tried three codes and still cant get excel to apply the code to each separate sheet. Any code I use, confuses excel and redirects me to the first sheet.
1st code I used
dim WS as worksheet
for each WS in sheets
(my code)
next WS
2nd code I used
For Each Worksheet In ThisWorkbook.worksheets
sheets("may","June","july").activate
(my code)
next worksheet
ive also tried, (worksheet.activate) but this code redirects me to the first sheet and losses the data on other sheets
Here's the current code I'm trying to get to work
Sub Check_in()
For Each Worksheet In ThisWorkbook.worksheets
worksheets("April", "May", "June").Activate
Dim code As String: code = InputBox("Please scan a barcode", "Scan procedure")
If code = "" Then MsgBox ("No code scanned"): Exit Sub
Dim NbChIn As Integer: NbChIn = application.CountIf(Range("STORE_RECORDS [CHECKED OUT on its way to analytical lab]"), code)
Dim NbChOut As Integer: NbChOut = application.CountIf(Range("STORE_RECORDS[SAMPLE RECEIVED from analytical lab]"), code)
If NbChIn > NbChOut And NbChIn > 0 Then
MsgBox ("This sample is already Checked-out" & Chr(10) & "Please click sample received and retry"): Exit Sub
Else
Cells(Rows.Count, 1).End(xlUp).Offset(1, 0) = code
Cells(Rows.Count, 1).End(xlUp).Offset(0, 1) = Now
End If
Next Worksheet
End Sub
Sub Check_Out()
Dim code As String: code = InputBox("Please scan a barcode", "Scan procedure")
If code = "" Then MsgBox ("No code scanned"): Exit Sub
Dim NbChIn As Integer: NbChIn = application.CountIf(Range("STORE_RECORDS[CHECKED OUT on its way to analytical lab]"), code)
Dim NbChOut As Integer: NbChOut = application.CountIf(Range("STORE_RECORDS[SAMPLE RECEIVED from analytical lab]"), code)
If NbChIn = NbChOut And NbChIn > 0 Then
MsgBox ("This sample has already been received" & Chr(10) & "Please check it out and retry"): Exit Sub
Else
If Range("STORE_RECORDS[CHECKED OUT on its way to analytical lab]").Find(code, , , xlWhole, , xlPrevious) Is Nothing Then MsgBox ("No match, ask Carlos !"): Exit Sub
Range("STORE_RECORDS[CHECKED OUT on its way to analytical lab]").Find(code, , , xlWhole, , xlPrevious).Offset(0, 2) = code
Range("STORE_RECORDS[CHECKED OUT on its way to analytical lab]").Find(code, , , xlWhole, , xlPrevious).Offset(0, 3) = Now
End If
End Sub'
code usually says wrong number of arguments, or object doesn't support this property or method. code only works on sheet 1 or in my case (April) I want this code to apply to each sheet, organized by months.

check in- check out sytem using a barcode scanner

I'm trying to create a check in/out system at a lab I work at. I'm not to experienced at using VBA. I was able to tinker with some formulas to get it to do what I wanted, but I wasn't fully successful in getting all the steps I wanted done.
So what I'm trying to do is check in samples using a barcode followed by a date in the cell right next to it.
I want this formula to apply to A2000 so I can check in multiple samples. I'm using an input box and I want this input box to be able to detect matched samples and place them in the checked out column C followed by a date in the cell right next to it.
I would appreciate any help you guys can give me.
Here's the code I am currently using.
Private Sub Worksheet_Activate()
Dim myValue As Variant
Dim code As Variant
Dim matchedCell As Variant
myValue = InputBox("Please scan a barcode")
Range("A2").Value = myValue
Set NextCell = Cells(Rows.Count, "A").End(xlUp)
If NextCell.Row > 1 Then NextCell = NextCell.Offset(1, 0)
Set matchedCell = Range("a2:a2000").Find(what:=code, LookIn:=xlValues, lookat:=xlWhole, MatchCase:=True)
If myValue = True Then Paste ("C2;C2000")
If Not matchedCell Is Nothing Then matchedCell.Offset(-1, 1).Value = Now
End Sub
To add data safety, I would differentiate the Check-In and the Check-Out process.
I'm not sure how you get the Code from the scanner ? Copied to prompt automatically ?
Anyway, below is my solution:
1.Transform your table into an excel table (CTRL+T) and name it "STORE_RECORDS" as below:
2.Create a module and paste following code:
Option Explicit
Sub Check_In()
Dim Code As String: Code = InputBox("Please scan a barcode", "Scan procedure")
If Code = "" Then MsgBox ("No code scanned"): Exit Sub
Dim NbChIn As Integer: NbChIn = Application.CountIf(Range("STORE_RECORDS[CHECK-IN]"), Code)
Dim NbChOut As Integer: NbChOut = Application.CountIf(Range("STORE_RECORDS[CHECK-OUT]"), Code)
If NbChIn > NbChOut And NbChIn > 0 Then
MsgBox ("This item is already Checked-In" & Chr(10) & "Please check it out and retry"): Exit Sub
Else
Cells(Rows.Count, 1).End(xlUp).Offset(1, 0) = Code
Cells(Rows.Count, 1).End(xlUp).Offset(0, 1) = Now
End If
End Sub
Sub Check_Out()
Dim Code As String: Code = InputBox("Please scan a barcode", "Scan procedure")
If Code = "" Then MsgBox ("No code scanned"): Exit Sub
Dim NbChIn As Integer: NbChIn = Application.CountIf(Range("STORE_RECORDS[CHECK-IN]"), Code)
Dim NbChOut As Integer: NbChOut = Application.CountIf(Range("STORE_RECORDS[CHECK-OUT]"), Code)
If NbChIn = NbChOut And NbChIn > 0 Then
MsgBox ("This item is already Checked-Out" & Chr(10) & "Please check it in and retry"): Exit Sub
Else
If Range("STORE_RECORDS[CHECK-IN]").Find(Code, , , xlWhole, , xlPrevious) Is Nothing Then MsgBox ("No match, ask Carlos !"): Exit Sub
Range("STORE_RECORDS[CHECK-IN]").Find(Code, , ,xlWhole , , xlPrevious).Offset(0, 2) = Code
Range("STORE_RECORDS[CHECK-IN]").Find(Code, , ,xlWhole , , xlPrevious).Offset(0, 3) = Now
End If
End Sub
3.Link Check-In and Check-Out buttons to respective procedures and you should be good to go.

Resources