Dynamically changing vlookup table - excel

I recorded this:
Range("B1").FormulaR1C1 = _
"=IF(VLOOKUP(RC1,sorted!R3C1:R35C33,8,FALSE)="""","""",VLOOKUP(RC1,sorted!R3C1:R35C33,8,FALSE))"
I need to have it update dynamically.
I found this (modified for my needs), but I'm not sure what to put in the "?" fields. Hopefully I'm on the right track:
With Worksheets("Move to New")
.Range("?").Offset(x, 0) = Application.WorksheetFunction.VLookup( _
.Range("?").Offset(x, 0), _
Worksheets("sorted").Range("?", .Range("?").End(xlDown)), 8, False)

I got it resolved.
Range("B1").FormulaR1C1 = "=IF(VLOOKUP(RC1,sorted!C1:C33,8,FALSE)="""","""",VLOOKUP(RC1,sorted!C1:C33,8,FALSE))"

Related

Opening a Specific Record in an Access Form From Excel

I'm writing a macro that will open an Access Database, open a form and display a specific record based on the contents of the ActiveCell. I have it mostly working, but the problem I'm having is that it opens a form that only contains the one record, so the arrow buttons at the bottom don't go to other records. Is there a way to open the form with all the records and then move to then one i want to show? I suspect it has to do with the search box at the bottom of the form, but I can't find any info about it on the internet.
Form opened by Macro:
Form opened manually:
Sub File_open()
Dim app as Object
Dim search As String: search = ActiveCell.Value
If (ActiveCell.Font.ColorIndex = 3) And (InStr(ActiveCell.Value, "-") <> 0) Then
'Open NCR Record
Set app = CreateObject("Access.Application")
app.Visible = True
app.OpenCurrentDatabase ("Z:\Quality\NCR Database\NCR Databse " & "20" & Left(ActiveCell.Value, 2) & "0101.accdb")
app.DoCmd.OpenForm "Issue Details", , , "[ID]=" & Abs(Replace(Right(search, 4), "-", ""))
Set app = Nothing
Exit Sub
End If
Msbox ("NCR Not Found.")
End Sub
UPDATE:
I've noticed that users of this database have been sloppy and the [ID] of the records don't line up with the number I get from my Abs(Replace(Right(search, 4), "-", "")) expression. I want to look at a textbox named [Title] whose control source is a field called [NCR Number] and use the search variable as is to find the record. I changed my code and now I just get a input box that is completely baffling to me:
app.DoCmd.OpenForm "Issue Details", WhereCondition:="[Title]=" & search
You're showing the form with DoCmd.OpenForm:
expression.OpenForm (FormName, View, FilterName, WhereCondition, DataMode, WindowMode, OpenArgs)
For FormName you're passing "Issue Details", skipping View and FilterName parameters, and then you provide a WhereCondition argument:
app.DoCmd.OpenForm "Issue Details", , , "[ID]=" & Abs(Replace(Right(search, 4), "-", ""))
That "[ID]=" & Abs(Replace(Right(search, 4), "-", "")) expression is the filter you're seeing.
Remove that argument, you'll remove the filter.
app.DoCmd.OpenForm "Issue Details"
Side note, don't skip optional positional arguments like that (, , ,) - consider using named arguments instead, it makes it much clearer what arguments go to what parameters:
Now you need to move the recordsets cursor to your wanted position (can be provided by.OpenArgs):
app.DoCmd.OpenForm "Issue Details", _
OpenArgs:="[ID]=" & Abs(Replace(Right(search, 4), "-", ""))
'below could be in the form itself, e-g- Form_Load, (then ref by Me)
With Forms("Issue Details").RecordsetClone
.FindFirst Forms("Issue Details").OpenArgs
If .NoMatch then
' reaction on id not found
Else
Forms("Issue Details").Bookmark = .Bookmark
End If
End With

Automatically Expand all "Table Columns" with specific name

I'm a beginner in coding and am not familiar with "M" modeling language. I have an XML file that I want to use to load the data in Query Editor. In the Query, I need to expand only the table columns with a specific name below:
view
viewfolder
Attribute:name
I have found the following post where they give a function by Chris Webb for expanding all the lists(below code).
= (TableToExpand as table, optional ColumnNumber as number) =>
let
ActualColumnNumber = if (ColumnNumber=null) then 0 else ColumnNumber,
ColumnName = Table.ColumnNames(TableToExpand){ActualColumnNumber},
ColumnContents = Table.Column(TableToExpand, ColumnName),
ColumnsToExpand = List.Distinct(List.Combine(List.Transform(ColumnContents, each if _ is table then Table.ColumnNames(_) else {}))),
NewColumnNames = List.Transform(ColumnsToExpand, each ColumnName & "." & _),
CanExpandCurrentColumn = List.Count(ColumnsToExpand)>0,
ExpandedTable = if CanExpandCurrentColumn then Table.ExpandTableColumn(TableToExpand, ColumnName, ColumnsToExpand, NewColumnNames) else TableToExpand,
NextColumnNumber = if CanExpandCurrentColumn then ActualColumnNumber else ActualColumnNumber+1,
OutputTable = if NextColumnNumber>(Table.ColumnCount(ExpandedTable)-1) then ExpandedTable else ExpandAll(ExpandedTable, NextColumnNumber)
in
OutputTable
But how to expand only desired lists/tables?
You should be able to simply put a filter on the old ColumnsToExpand line.
That is,
TableColumns = //This is the old ColumnsToExpand definition renamed.
List.Distinct(List.Combine(List.Transform(ColumnContents, each if _ is table then Table.ColumnNames(_) else {}))),
ColumnsToExpand =
List.Select(TableColumns, each (_ = "view" or _ = "viewfolder" or _ = "Attribute:name")),
Or in one line like this,
ColumsToExpand = List.Select(List.Distinct(List.Combine(List.Transform(ColumnContents, each if _ is table then Table.ColumnNames(_) else {}))), each (_ = "view" or _ = "viewfolder" or _ = "Attribute:name")),

How can I use Index Match as Worksheet Functions?

I have a variable named 'searchVal' that is generated dynamically. Now, I'm trying to pass this string into Index/Match, and I'm getting tripped up somewhere. Maybe it's some kind of double-quotes thing, but I tried that and it still didn't work.
Here is my non-working function.
ID = Application.WorksheetFunction.Index(Sheets(""360Tasklist"").Range(""B2:B1000""), Application.WorksheetFunction.Match(" & searchVal & ", Sheets(""360Tasklist"").Range(""C2:C1000""), 0), 0)
This isn't right either.
ID = "Application.WorksheetFunction.Index(Sheets(""360Tasklist"").Range(""B2:B1000""), Application.WorksheetFunction.Match(" & searchVal & ", Sheets(""360Tasklist"").Range(""C2:C1000""), 0), 0)"
I must be close though... Any thoughts?
Thanks.

Inline null check for string in vba

iam searching a way to check if a string is empty before converting it to date, problem i that i want to avoid if-else since i have to use it on multiple variable in single statement:
Call MyObj.Insert(CInt(Me.ddlFiltroPD), _
CInt(Me.Parent!ddlFiltroEsito), _
CInt(Nz(ddlFiltroPD.Column(1))), _
Nz(txtPuntoDebolezza, ""), _
CInt(Nz(Me.ddlRilevanza, 0)), _
Nz(txtInterventi, ""), _
Nz(txtOwner, ""), _
CDate(txtData1), _
CDate(txtData2), _
CDate(txtData3), _
CDate(txtData4), _
Nz(txtMotivazioneChiusura) _
)
txtData1, txtData2, txtData3 and txtData4 can be null and i have to convert it to a data when they are not null
i have thought to create a function to do the convertion or to use some temp variables but iam looking for something better
You can use this expression:
IIf(txtdata1 = vbNullString, "", CDate(txtdata1))
i solved in this way
Call MyObj.Insert(..., _
txtData1, _
txtData2, _
txtData3, _
txtData4, _
)
in MyObj.Insert i change parameter to variant and i transform parameter using Format(txtData1, "YYYYMMDD")

VBA - Excel : Vlookup crashes my program when no match found

In my program, the user types a Zip Code and gets as an output information related to the Zip Code (province, city, district). To do this, I use the Vlookup function.
So, the user :
Types a Zip code in the main sheet
The program search in a database (in another sheet) in which Zip Code are associated to City, Province, District.
When there is a match, it sends the result to the main pages, so the user can get a city, province, district just by typing the Zip Code. Quite simple process.
I use this code to do so :
If Range("J9").Value <> "N/A" Then 'if there is actually a zip code entered by the user (if not, it will be "N/A")
cityZip = Application.WorksheetFunction.VLookup(sMain.Range("J9").Value,
sZipCodes.Range("B2:E864"), 3, False)
barangayZip = Application.WorksheetFunction.VLookup(sMain.Range("J9").Value,
sZipCodes.Range("B2:E864"), 2, False)
provinceZip = Application.WorksheetFunction.VLookup(sMain.Range("J9").Value,
sZipCodes.Range("B2:E864"), 4, False)
sMain.Range("J7").Value = provinceZip
sMain.Range("J13").Value = cityZip
sMain.Range("J16").Value = barangayZip
Else
End If
It works perfectly when there is a Zip Code which is in my database. But if not, it crashes the execution of the program and I have an error message (like "execution error '1004', unable to read the Vlookup ...).
How to modify my code to just say that if there is no match, then it should just do nothing? I don't know how to introduce this request in a Vlookup function.
Thanks in advance !
EDIT : here is my new code, after following Tim Williams suggestion :
'Using Zip Code
If Range("J9").Value <> "N/A" Then
provinceZip = Application.Lookup(sMain.Range("J9").Value, sZipCodes.Range("B2:E907"), 4, False)
If IsError(provinceZip) = False Then
cityZip = Application.Lookup(sMain.Range("J9").Value, sZipCodes.Range("B2:E907"), 3, False)
barangayZip = Application.Lookup(sMain.Range("J9").Value, sZipCodes.Range("B2:E907"), 2, False)
sMain.Range("J7").Value = provinceZip
sMain.Range("J13").Value = cityZip
sMain.Range("J16").Value = barangayZip
Else
'do nothing
End If
End If
My error is on this line :
provinceZip = Application.Lookup(sMain.Range("J9").Value, sZipCodes.Range("B2:E907"), 4, False)
=> Error 1004, invalid number of arguments
You should read up on VBA error handling. A source such as http://www.cpearson.com/excel/errorhandling.htm might help. That said, try the following code.
You want something like:
Public Function SafeVlookup(lookup_value, table_array, _
col_index, range_lookup, error_value) As Variant
On Error Resume Next
Err.Clear
return_value = Application.WorksheetFunction.VLookup(lookup_value, _
table_array, col_index, range_lookup)
If Err <> 0 Then
return_value = error_value
End If
SafeVlookup = return_value
On Error GoTo 0
End Function
In your code you might call it like:
cityZip = SafeVlookup(sMain.Range("J9").Value, sZipCodes.Range("B2:E864"), 3, _
False, "")
The last parameter is the default value to return if the vlookup failed. So in this example it'd return an empty string.
I usually wrap the vlookup() with an iferror() which contains the default value.
The syntax would be as follows:
iferror(vlookup(....), <default value when lookup fails>)
You can also do something like this:
Dim result as variant
result = Application.vlookup(......)
If IsError(result) Then
' What to do if an error occurs
Else
' what you would normally do
End if
You changed from Vlookup to Lookup, which has less arguments. Using only 2 arguments, you should be fine: provinceZip = Application.Lookup(sMain.Range("J9").Value, sZipCodes.Range("B2:E907") )
SafeVlookup is a good function.
I am still learning VB.
I changed like this and it works for me.
Function SafeVlookup(lookup_value, _
range_lookup, col_index, error_value) As Variant
.....
return_value = Application.WorksheetFunction.vlookup(lookup_value, _
range_lookup, col_index, error_value)
....
End Function
Hope I can use it like this.

Resources