I have an excel worksheet that has two sheets. On the first one i have the printable page and the second sheet is for the first to pull data from using vlookup. The second sheet consists of 8 columns. The first column is the ID that's being used by vlookup on the first page. The second is for first/last name. What i want to do is to make excel search for this (first/last name) in an access database and then retrieve and fill 3 other columns from the data in access. There are 2 tables that i want it to look into. It will find the name in either one of them and there are no duplicates. Does anyone have any idea how i might achieve this? Thanks!
You have a few choices. One is to use an .ODC using "Data-Get External Data". If you go through the wizard you can store the search criteria in the external data link (and if desired save this as an .ODC file). If you record a Macro when doing this, you will see where you can alter the recorded VBA code to substitute your own criteria from Excel (e.g, First/Lame name).
Another way, if your data isn't too big is to bring in a single sheet with "Data-GetExternalData" containing all your data then use VLookup (or index/match) to just retrieve the appropriate names. This works well when your database is not too big to bring entirely into Excel, efficiently.
But I use the following code because it's slick and doesn't require exposing any connection info (including passwords) in the .ODC (stored external data link). It's also faster. In this example, I use ADO because it's a SQL/Server database, but if the data is in Access (.ACCDB or MDB) then you can use ordinary DAO. If you need the ADO, don't forget to include the ADO library in your references.
In my example, I used a date range to find the data I wanted. In your case, it would be Lname and Fname instead of a date range.
This Excel VBA code is what I use.
Sub RefreshReport()
On Error GoTo Err_Handler
verrevent = "RefreshReport"
Dim rs As New ADODB.Recordset
If cn.State = 0 Then OpenNewConnection
Dim xlRange As Excel.Range
'Delete prior data
Range("MyTargetTable").EntireRow.Delete
'Call sproc to fetch member match
'This uses SPROC, but could be any SQL statement passing search criteria from Excel
vsql = "sproc_my_procedure '" & Range("BegDate") & "' ,'" & Range("EndDate") & "'"
'Call sproc to fetch member match
Set xlRange = Range("MyTargetDataSheet!A2")
Set rs = cn.Execute(vsql)
xlRange.Cells.CopyFromRecordset rs
'Refresh a pivot table if you have one
Set pt = Sheets("Summary").PivotTables("PivotTable1")
pt.RefreshTable
MsgBox ("Refresh Complete")
Exit_Proc:
Exit Sub
Err_Handler:
MsgBox ("Refresh program error. Please snip and send." & vbCrLf & vbCrLf & "Err " & Err.Number & " " & verrevent & " " & vbCrLf & Err.Description & vbCrLf)
Resume Exit_Proc
End Sub
Related
I'm thinking this might have to use VBA, but is there any way to create the following sequence of actions within the built-in MS Access macro features?:
Run delete query for table (table1)
Run append query for table1
Table1 is exported where the following are true:
table1 is exported as .xlsx
the date is added to the end of the file name (table1_200414.xlsx)
the file is exported to a specific file path
I've seen step #3 done with VBA, but I'm wanting to be able to copy this macro between databases, so I don't know if the VBA code would be copied by a simple copy-paste of the macro. If it is, then how would you do this in VBA?
The best way to do this is within VBA, not just because I think that step 3 can only be done using VBA, but also because you get error handling. And also, if you use in line SQL statements to perform your deletes/appends, you don't need to worry about copying extra queries over to another database - you just copy over the procedure.
Here is a short VBA procedure that performs all 3 steps for you:
Sub sExportData()
On Error GoTo E_Handle
Dim strFolder As String
Dim strFile As String
Dim strID As String
CurrentDb.Execute "DELETE * FROM [Table1];"
CurrentDb.Execute "INSERT INTO [Table1] SELECT * FROM [TableAppend];"
strFolder = "J:\downloads\"
strID=DLookup("ID","Table1")
strFile = "Table1_" & strID & Format(Date, "yymmdd") & ".xlsx"
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel12Xml, "Table1", strFolder & strFile, True
sExit:
On Error Resume Next
Exit Sub
E_Handle:
MsgBox Err.Description & vbCrLf & vbCrLf & "sExportData", vbOKOnly + vbCritical, "Error: " & Err.Number
Resume sExit
End Sub
Without knowing exactly what you are doing, it may be that you don't need to do the delete/append to Table1. It may be possible to output the data selected in the append query directly to an Excel file.
Regards,
I have a Worksheet called "TEMPLATE" with a PowerQuery "TEMPLATE_Query" in it which works. The Powerquery requests a CSV-file from a website.
Now, using VBA in a loop, I make N copies of this sheet, resulting in worksheets named "Template (X)" and Powerquerys named "TEMPLATE_Query (X)". X=1..N. In my VBA code, I modify the Powerquery Formulas to request a different CSV file. Until here, it works alright. The Powerquerys run and receive different CSV files in all those Worksheets.
Here's the problem:
When I change the name of the Worksheet using VBA during my loop where I create the copies, the Powerquerys fail afterwards. Saying like "Download failed, connection only". So apparently the Powerquery doesn't have a reference to the correct sheetname anymore. The same happens when I rename the Powerquery and leave the Worksheet Name the same.
My goal is, to rename the Worksheet AND the Powerquery both in my VBA loop.
But why does this break the Queries?
I had the same problem a little while ago. If I remember correctly, it breaks because the query still wants to access something with a different name. I don't know why Excel does not change the reference when you rename a query. It does not even automatically changes it if you rename it manually with a right click. If you look at the query, right click it and then switch over to properties or what ever the middle tab is called, there you can see some details.
Long story short, this is how I fixed mine:
Sub Create_new_connection()
'On Error Resume Next
'Count the current amount of queries and save that number to refer to it later
QueryCount = ThisWorkbook.Queries.Count
'Copy the template and rename it
ThisWorkbook.Sheets("Template").Copy after:=ThisWorkbook.Sheets("Template")
ThisWorkbook.Sheets(3).Name = "Put a name here"
'Change the name of the query
ThisWorkbook.Queries.Item(QueryCount + 1).Name = "New Query Name"
'Change the names of the new table
ThisWorkbook.Sheets(3).ListObjects(1).Name = "I had a table I wanted to rename"
'Change the formula of the new connection
NewFormula = Replace(ThisWorkbook.Queries.Item(1).Formula, ThisWorkbook.Sheets("Create New List").ListObjects("Template").DataBodyRange(1, 1), ThisWorkbook.Sheets("Create New List").ListObjects("FAUF").DataBodyRange(1, 1))
ThisWorkbook.Queries.Item(QueryCount + 1).Formula = NewFormula
'Connect the new table to the new connection and
ThisWorkbook.Sheets(3).ListObjects(1).QueryTable.WorkbookConnection = "Abfrage - " & ThisWorkbook.Queries.Item(QueryCount + 1).Name
ThisWorkbook.Sheets(3).ListObjects(1).QueryTable.Connection = "OLEDB;Provider=Microsoft.Mashup.OleDb.1;Data Source=$Workbook$;Location=" & """" & ThisWorkbook.Queries.Item(QueryCount + 1).Name & """" & ";Extended Properties=" & """" & """"
ThisWorkbook.Sheets(3).ListObjects(1).QueryTable.CommandText = "SELECT * FROM [" & ThisWorkbook.Queries.Item(QueryCount + 1).Name & "]"
'Refresh the new connection
ThisWorkbook.Sheets(3).ListObjects(1).QueryTable.Refresh BackgroundQuery:=False
End Sub
The second to last bunch, the 3 modifying the connection are the important ones. This is on a German Excel tho, so you may need to change the "Abfrage - " bit to fit your language. It's just important that you correctly change the WorkbookConnection, Connection and CommantText correctly.
I am trying to enter a Vlookup formula into Column S of a worksheet named "FY_16". I need the user to select the file (which changes each month) that the "table array" for the formula is in.
Each month the file changes, but the column I want to look up to will always be the same - Column W (but have varying number of rows). The "table array" that the formula will look up to is part of a table.
My code at this point is below:
Private Function UseFileDialogOpen()
MsgBox ("When the browse window opens: please select the previous months published FY16 Consulting SKU File")
Dim myString As String
' Open the file dialog
With Application.FileDialog(msoFileDialogFilePicker)
.AllowMultiSelect = False
.Show
If .SelectedItems.Count = 1 Then
myString = .SelectedItems(1)
'MsgBox myString
UseFileDialogOpen = myString
Else
MsgBox ("Failed to properly open file")
myString = "fail"
UseFileDialogOpen = myString
End If
End With
End Function
Sub Vlookup
Dim filelocation 'as what?????
filelocation = UseFileDialogOpen()
Worksheets("FY_16").Range("T2:T" & LastRow).FormulaR1C1 = "=vlookup(RC[-3], [" & myString & "] PA Rev!R1C23:R900000C23,1,false)"
My issue occurs on the final line of code. I receive a "run time error 1004 : application defined or object defined" message.
I know my syntax is incorrect for the vlookup in a few ways. I am not sure the "& myString & " is correct, perhaps this should be "filelocation"?
I also don't believe R1C1 can be used to name a range like I have in the vlookup. I typically would use
.Range(Cells(2,23), Cells(90000,23))
But I am not sure how to use that with the variable that holds the selected file name.
Also, I am using the 90000 row because this will go past my data each month (usually row count is around 75000). I would much rather find the exact row number but I don't believe this can be done without opening the "target file" selected by the user. If there is a way to achieve this, please offer any advice!
I am wondering if there is a way to use the Table Names to set the table array?
The non-VBA vlookup is as follows:
=VLOOKUP(Q2,'TargetFile.xlsb'!REV[[#All],[Net New Match]],1,FALSE)
TargetFile is the user selected file
REV is the worksheet the table array is on
Net New Match is the column I want to look up to (the entire column)
I played around with using these table names but couldn't get the syntax correct (possibly because the rest of the formula code is incorrect also).
Any help will be greatly appreciated. Let me know if any clarification is needed.
Mike
The correct syntax for accessing a range in an unopened workbook would be something that looks like 'C:\Temp\[Book2.xlsx]PA Rev'!R1C23:R900000C23. That won't be the same format that comes from the UseFileDialogOpen function.
You also can't use myString within your Vlookup subroutine because you defined that variable to be local to UseFileDialogOpen - but you can use filelocation which you have used to store the result from UseFileDialogOpen. But, as I said, it won't be in the right format anyway, so it will require a bit of reformatting.
The following command should do the necessary reformatting:
Worksheets("FY_16").Range("T2:T" & LastRow).FormulaR1C1 = _
"=vlookup(RC[-3],'" & Left(fileLocation, InStrRev(fileLocation, "\")) & _
"[" & Mid(fileLocation, InStrRev(fileLocation, "\") + 1) & _
"]PA Rev'!R1C23:R90000C23,1,false)"
I have ~200 Excel workbooks each with a unique name, in its own folder, something like C:\docs\daily\XXXX\XXXX_Daily_Report_20150920.xls, where XXXX is just an alphanumeric identifier and the date is obviously just today's date.
I need to get one cell (the same cell, "I2") from all 200+ Excel workbooks every single day.
I know you can link Excel workbooks to Access but I can't figure out a way to make it link to a different workbook each day and I'm wondering if there is a query to simply get that one cell instead of linking the entire Excel workbook.
Right now I have Excel VBA that opens each Excel file and copies and pastes it into the corresponding row/column in my workbook...but since it does this 200+ times I'm wondering if Access will have a faster solution.
Is there any way to write a query/macro in Access that will link the cell I2 from each day's new report (so tomorrow's would be "XXXX Daily Report 20150921.xls") and just populate a table with XXXX in the first column and the value of I2 in the second?
Function import()
source_date = InputBox("date (yyyymmdd)")
Set db = CurrentDb()
db.Execute ("delete * from [DailyData]")
Set app = CreateObject("Excel.Application")
Set FSO = CreateObject("Scripting.FileSystemObject")
Set folder_list = FSO.GetFolder("C:\docs\daily").subfolders
For Each Fldr In folder_list
Source = Fldr.Name
SourceFile = "c:\docs\daily\" & Source & "\" & Source & "_daily_reports_" & source_date & ".xlsm"
Set WB = app.workbooks.Open(SourceFile)
amount = WB.sheets("sheet1").range("I2").Value
SQL = "Insert into [DailyData] (source, amount) select '" & Source & "'," & amount
db.Execute (SQL)
WB.Close
Next Fldr
MsgBox ("done")
End Function
This takes all the files for a specific date and puts the input into a table called DailyData, with fields for Source and Amount.
Note - modified 9/22 to eliminate the inside loop and If block - this assumes every folder will have a file for the current day's update. If not, you may want to verify that the file exists before you try to open it.
I am new to VBA but I am working on setting up a Database in Excel (I realize that Access is much better suitedm but I am doing this for someone else).
I have a source file that has information in the range B5:B17, this form will be for others to send to the person managing the database. I need to write a VBA code that will select the data in the source range, transpose it, find a match is one exists, then either overwrite the existing data or add to the next blank row. Here is the sequence:
Prompts the database manager to open the source file (I know how to do this)
Transpose the data in B5:B17
Search for a match in cell B7 (source file) and match it to values in column C (database)
Overwrite the matching data
If no match exists, then write to the next empty row.
I have been using the following code as a guide but it has some limitations. The source file has to be open, also, I am not sure how to include the Transpose function to this code. Any help id appreciated
This should do what you are looking for.
Sub Sample()
Dim rngEnteredID As Range
Dim lngRowWithMatch As Range
Set rngEnteredID = Sheets("Sheet1").Range("B7")
On Error GoTo NoMatch
lngRowWithMatch = WorksheetFunction.Match(rngEnteredID.Value, Sheets("Sheet2").Range("C:C"), 0)
On Error GoTo 0
Sheets("Sheet2").Range("A" & lngRowWithMatch & ":K" & lngRowWithMatch).Value = Application.Transpose(Sheets("Sheet1").Range("B5:B17"))
Exit Sub
NoMatch:
Dim lngEmptyRow As Long
lngEmptyRow = Sheets("Sheet2").Cells(Rows.Count, 3).End(xlUp).Row + 1
Sheets("Sheet2").Range("A" & lngEmptyRow & ":K" & lngEmptyRow).Value = Application.Transpose(Sheets("Sheet1").Range("B5:B17"))
End Sub