simple import form in Access - ms-access

how to create an access form which has import excel file button. and after selecting excel file it automatically creates a table in the database with collumn headers as excel first row and data as excel other rows. if you think i am not putting any effort please give me suggestion or reference and ill do it on my own.

For versions of Access since 2003, you can use the File Dialog to allow the user to browse for the file they want, prior to that, you can use API calls. If this is overkill for you, you can have the user type in the file name and path, but you will have to check that it exists using code (Dir may suit).
It would be best to use TransferSpreadsheet method of the DoCmd object (available in any version of Access from, AFAIK, 1997 onward) to import the spreadsheet. This can be run as VBA (code) or a macro.

If we assume that you are able to create a form and wire up a button you have two issues:
The file open dialog.
Triggering the import.
For 1 you should be able to use the standard Microsoft file dialogs - my VB.OLD and Access are spectacularly rusty (no access 2007) but you can reference the appropriate COM assemblies from Access after which it becomes fairly easy.
2 is a bit more interesting - I beleive you can pretty much do this by menu selection from within access in which case, at least as a first step, you should be able to automate the same steps - pretty much anything you can do from a menu you can also do by calling the relevant command from VBA. The more complex solution would be to create VBA logic to create a linked table that links to the Excel file and then do a create table query and then drop the link.
In terms of effort, the form is something one would expect you to be able to do without much help - however automating something like an import from excel is not necessarily obvious.

An example using Access 2003 would be as follows for selecting a file:
Dim fDialog As Office.FileDialog
Dim strFile As String
Set fDialog = Application.FileDialog(msoFileDialogFilePicker)
With fDialog
.InitialFileName = "C:\temp\*.xls"
.Filters.Clear
.Filters.Add "Excel file", "*.xls"
.Filters.Add "All Files", "*.*"
If .Show = True Then
strFile = .SelectedItems(1)
End If
End With
Debug.Print strFile
Note you would need to add a Reference to the Office 12 Object Library
To Import the file you can use the TransferSpreadsheet Function of the DoCmd Object. For E.g.
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel9, "ExcelImport", strFile, True
The Access table called ExcelImport would have to already exist in the database.

Related

Access VBA Macro to run pass through query

I have a pass through query built in Teradata set to export data to an Excel spreadsheet. I'm trying to automate it, but when I run the macro or open the query, a window pops up asking for the data source. I have an ODBC connection created and I'm thinking there has to be a way to make the macro pass the data source name so it will run without interaction.
Edit: Adding Macro as requested
Function AutoExec()
On Error GoTo AutoExec_Err
DoCmd.OutputTo acOutputQuery, "Performance Interval Data", "ExcelWorkbook(*.xlsx)", _
"filepath\filename.xlsx", False, "", , acExportQualityPrint
DoCmd.Quit acExit
AutoExec_Exit:
Exit Function
AutoExec_Err:
MsgBox Error$
Resume AutoExec_Exit
End Function
Couple of concerns, (can't validate any of this right now as I do not currently have access to Access for testing), but it looks like:
You're trying to OutputTo a query, to the best of my knowledge that
is not feasible.
Your file path is setup as filepath\filename.xlsx unless that is the actual location and name of your Excel sheet, something seems
wrong there to me.
I don't really think this macro relates to an ODBC of any sort in its current state.
But, you should at least start with fixing the filepath issue. That should be the full path to your Excel file and the full name of the file as well. (i.e. C:\TEMP\TestExcelSheet.xlsx)
All that being said, you may want to just go with something like this (although its a little difficult to tell if this is what you actually want or not):
'Export Excel file from Query
DoCmd.TransferSpreadsheet acExport, , "acOutputQuery", _
"C:\TEMP\TestExcelSheet.xlsx", True
NOTE: "acOutputQuery" should be the actual name of your passthrough query, "C:\TEMP\TestExcelSheet.xlsx" would be your destination path, and True adds the query's headers into the sheet, False to ignore the headers.

MS Access Auto De-link and Re-link an Excel file?

I have a link-table from an Excel file, but sometimes it "breaks" for reasons unknown to me (other people manipulate this file externally and for whatever reason, the link in the database corrupts even though the filename is the same, etc).
The only way I can fix this issue is by delinking the file and then re-linking it. Is there a way to do this automatically when someone opens the database? (I know about autoexec macros and VBA and everything, but I was unable to find VBA code to delete the old link and re-link the file again).
if the file path does not change you can simply relink the source. You can do it to connect all the linked tables to be connected or you can specifically tell one linked table to be reconnected.
pseudo would be:
Go through your table collection
check if the table is a linked table / or any condition
use the .Connect property to set/renew the connectionstring/path for linked tables.
use the .RefreshLink method to reconnect the table
in code it would be something like this:
For Each tdf In db.TableDefs
If tdf.connect <> vbNullString Then
'you can renew the connectionstring if you want by
'tdf.connect = Your_connectionString & ";TABLE=" & tdf.name
'and to reconnect
tdf.RefreshLink
End If
Next tdf

Reattaching [Event Procedure] in Access

Due to requirements to not share data between clients, I have an MS Access 2010 data base that I use to extract data from our SQL Server into a small .accdb which we then send to a client, they modify, then I load the data back to the Server.
In my 'Master' Access database (EDIT2: I use Access as a front end to SQL Server), I have a button that will create a client specific .accdb (EDIT2: This has a local table that contains the client's specific data for them to moidify). This code simply copies a template .accdb with forms, code, etc & names it appropriately for the client.
Unfortunately when this copy is made, all the event procedure connections are lost from the properties box. The code still exists in the module, though. This is a fairly well-known issue and is well documented on Google. The general solution is to go through each form & reset the properties for every form & control that needs an event, then Access will reconnect it with the existing code. That's ok, once. I'll have this copy/loss issue dozens or hundreds of times.
I found one reference from ~2003 March, 2004 to dynamically identify missing code (EDIT2: [Event Procedure] references in the properties box) & set the property to [Event Procedure] to fix this. However, when trying to identify if an object should have an event handler, the code relies on this statement
DLookup("EventProcedureSuffix", "EventProcedures", "EventName = '" & prpCurr.Name & "'")
and that generates an error 3078 saying it cannot find a table or query named 'EventProcedures' (EDIT2: which seems to have been a system table in the older version of Access that the code was based on). Does anyone know what happened to the 'EventProcedures' table in Access 2010? Has it been renamed, is it no longer accessible, is there a replacement?
This also begs the question of how do I fire this code in the first place. I have it on the OnOpen event of the main form that is opened when the DB is opened, but if the event handler is disconnected, that won't fire, either...
EDIT: Found the link to the source of the code I'm using: http://www.accessmvp.com/djsteele/Access/AA200403.zip
Instead of trying to re-attach the Event Procedures after the fact you might try to find a method that creates a new user database in a way that preserves the Event Procedure links.
The following Access 2010 code seems to work fine for me. It creates an Access 2003 format .mdb file and then exports a Table and a Form. The form has a button with code behind it, and the button works fine when I open the form within the .mdb file.
Option Compare Database
Option Explicit
Public Function CreateUserDatabase()
Dim fd As Object ' Office.FileDialog
Dim db As DAO.Database
Dim newDbPath As String
Set fd = Application.FileDialog(2) ' msoFileDialogSaveAs
fd.Title = "Save User Database As..."
fd.InitialFileName = "UserDB.mdb"
fd.Show
If fd.SelectedItems.Count <> 0 Then
newDbPath = fd.SelectedItems(1)
If UCase(Right(newDbPath, 4)) <> ".MDB" Then
newDbPath = newDbPath & ".mdb"
End If
On Error Resume Next
Kill newDbPath
On Error GoTo 0
Set db = DBEngine(0).CreateDatabase(newDbPath, dbLangGeneral, dbVersion40)
db.Close
Set db = Nothing
DoCmd.TransferDatabase acExport, "Microsoft Access", newDbPath, acTable, "UserData", "UserData", False
DoCmd.TransferDatabase acExport, "Microsoft Access", newDbPath, acForm, "UserForm", "UserForm", False
MsgBox "The user database has been created.", vbInformation
End If
Set fd = Nothing
End Function

Microsoft office Access database engine could not find the object

I created a test MS Access DB to export a table to Excel and a text file.
This works for Excel:
DoCmd.OutputTo acOutputQuery, "QryExportToExcel", _
acFormatXLS, XFile, False
For the text file, I created a specification and used this code
DoCmd.TransferText acExportDelim, "Mytable Import Specification", "mytable", "D:\myfolder\test1.txt", False
In the error message, I get "test1#txt".
The Microsoft Office Access database engine could not find the object
"test1#txt". Make sure the object exists and that you spell its name
and the path name correctly.
I tried creating test1.txt in the same path. To my surprise, this deleted the file which is already present.
Software: MS ACCESS 2007
The Microsoft Office Access databasse engine could not find the object "test1#txt". Make sure the object exists and that you spell its name and path name correctly.
This is a generic (and rather useless) error message that Access outputs in case anything goes wrong. One example would be a misspelled field name in the import/export specification.
You can get the "real" error message by trying the import operation "manually" in the Access user interface (rather than through code).
The question author reported the problem was "because I was using an Import Specification for Exporting a file."
They resolved the problem by using an Export Specification.
Because you are doing DoCmd.TransferText, Access is expecting that the file Test1.txt exists in that location. Try creating the file first, and then do a transfer of the text.
You can try this code before the export to create the file:
Public Sub CreateExportFile()
Dim strFileName As String
Dim SomeStringToOutput
strFileName = "d:\myfolder\test1.txt"
Open strFileName For Output As #1
End Sub
I was having a similar situation and found that a file schema.ini was in the destination folder. This was created when an acExportMerge was performed previously and it caused this error. Make sure that file has been deleted prior to executing a new TransferText.

How can I modify a saved Microsoft Access 2007 or 2010 Import Specification?

Does anyone know how to modify an existing import specification in Microsoft Access 2007 or 2010? In older versions there used to be an Advanced button presented during the import wizard that allowed you to select and edit an existing specification. I no longer see this feature but hope that it still exists and has just been moved somewhere else.
I am able to use this feature on my machine using MS Access 2007.
On the Ribbon, select External Data
Select the "Text File" option
This displays the Get External Data Wizard
Specify the location of the file you wish to import
Click OK. This displays the "Import Text Wizard"
On the bottom of this dialog screen is the Advanced button you referenced
Clicking on this button should display the Import Specification screen and allow you to select and modify an existing import spec.
For what its worth, I'm using Access 2007 SP1
I don't believe there is a direct supported way. However, if you are desparate, then under navigation options, select to show system objects. Then in your table list, system tables will appear. Two tables are of interest here: MSysIMEXspecs and MSysIMEXColumns. You'll be able edit import and export information. Good luck!
Tim Lentine's answer seems to be true even in the full release. There is just one other thing I would like to mention.
If you complete your import without going into "Advanced..." and saving the spec, but you do save the import for reuse at the end of the wizard (new feature AFAIK), you will not be able to go back and edit that spec. It is built into the "Saved Import". This may be what Knox was referring to.
You can, however, do a partial work around:
Import a new file (or the same one all over again) but,
This time choose to append, instead of making a new
Click OK.
Go into "advanced" All your column heading and data-types will be there.
Now you can make the changes you need and save the spec inside that dialog. Then cancel out of that import (that is not what you wanted anyway, right?)
You can then use that spec for any further imports. It's not a full solution, but saves some of the work.
Below are three functions you can use to alter and use the MS Access 2010 Import Specification. The third sub changes the name of an existing import specification. The second sub allows you to change any xml text in the import spec. This is useful if you need to change column names, data types, add columns, change the import file location, etc.. In essence anything you want modify for an existing spec. The first Sub is a routine that allows you to call an existing import spec, modify it for a specific file you are attempting to import, importing that file, and then deleting the modified spec, keeping the import spec "template" unaltered and intact. Enjoy.
Public Sub MyExcelTransfer(myTempTable As String, myPath As String)
On Error GoTo ERR_Handler:
Dim mySpec As ImportExportSpecification
Dim myNewSpec As ImportExportSpecification
Dim x As Integer
For x = 0 To CurrentProject.ImportExportSpecifications.Count - 1
If CurrentProject.ImportExportSpecifications.Item(x).Name = "TemporaryImport" Then
CurrentProject.ImportExportSpecifications.Item("TemporaryImport").Delete
x = CurrentProject.ImportExportSpecifications.Count
End If
Next x
Set mySpec = CurrentProject.ImportExportSpecifications.Item(myTempTable)
CurrentProject.ImportExportSpecifications.Add "TemporaryImport", mySpec.XML
Set myNewSpec = CurrentProject.ImportExportSpecifications.Item("TemporaryImport")
myNewSpec.XML = Replace(myNewSpec.XML, "\\MyComputer\ChangeThis", myPath)
myNewSpec.Execute
myNewSpec.Delete
Set mySpec = Nothing
Set myNewSpec = Nothing
exit_ErrHandler:
For x = 0 To CurrentProject.ImportExportSpecifications.Count - 1
If CurrentProject.ImportExportSpecifications.Item(x).Name = "TemporaryImport" Then
CurrentProject.ImportExportSpecifications.Item("TemporaryImport").Delete
x = CurrentProject.ImportExportSpecifications.Count
End If
Next x
Exit Sub
ERR_Handler:
MsgBox Err.Description
Resume exit_ErrHandler
End Sub
Public Sub fixImportSpecs(myTable As String, strFind As String, strRepl As String)
Dim mySpec As ImportExportSpecification
Set mySpec = CurrentProject.ImportExportSpecifications.Item(myTable)
mySpec.XML = Replace(mySpec.XML, strFind, strRepl)
Set mySpec = Nothing
End Sub
Public Sub MyExcelChangeName(OldName As String, NewName As String)
Dim mySpec As ImportExportSpecification
Dim myNewSpec As ImportExportSpecification
Set mySpec = CurrentProject.ImportExportSpecifications.Item(OldName)
CurrentProject.ImportExportSpecifications.Add NewName, mySpec.XML
mySpec.Delete
Set mySpec = Nothing
Set myNewSpec = Nothing
End Sub
When I want to examine or change an import / export specification I query the tables in MS Access where the specification is defined.
SELECT
MSysIMEXSpecs.SpecName,
MSysIMexColumns.*
FROM
MSysIMEXSpecs
LEFT JOIN MSysIMEXColumns
ON MSysIMEXSpecs.SpecID = MSysIMEXColumns.SpecID
WHERE
SpecName = 'MySpecName'
ORDER BY
MSysIMEXSpecs.SpecID, MSysIMEXColumns.Start;
You can also use an UPDATE or INSERT statement to alter existing columns or insert and append new columns to an existing specification. You can create entirely new specifications using this methodology.
Another great option is the free V-Tools addin for Microsoft Access. Among other helpful tools it has a form to edit and save the Import/Export specifications.
Note: As of version 1.83, there is a bug in enumerating the code pages on Windows 10. (Apparently due to a missing/changed API function in Windows 10) The tools still works great, you just need to comment out a few lines of code or step past it in the debug window.
This has been a real life-saver for me in editing a complex import spec for our online orders.
Why so complicated?
Just check System Objects in Access-Options/Current Database/Navigation Options/Show System Objects
Open Table "MSysIMEXSpecs" and change according to your needs - its easy to read...
Tim Lentine's answer works IF you have yours specs saved. Your question did not specify that, it only stated you had imported the data. His method would not save your specs that way.
The way to save the spec of that current import is to re-open the import, hit "apend" and that will allow you to use your current import settings that MS Access picked up. (This is useful if your want to keep the import specs from an Excel format you worked on prior to importing into MS ACCESS.)
Once you're in the apend option, use Tim's instructions, which is using the advanced option and "Save As." From there, simply click cancel, and you can now import any other similar data to various tables, etc.
I have just discovered an apparent bug in the whole Saved Import/XML setup in Access. Also frustrated by the rigidity of the Saved Import system, I created forms and wrote code to pick apart the XML in which the Saved Import specs are stored, to the point that I could use this tool to actually create a Saved Import from scratch via coded examination of a source Excel workbook.
What I've found out is that, while Access correctly imports a worksheet per modifications of default settings by the user (for example, it likes to take any column with a header name ending with "ID" and make it an indexed field in the resulting table, but you can cancel this during the import process), and while it also correctly creates XML in accordance to the user changes, if you then drop the table and use the Saved Import to re-import the worksheet, it ignores the XML import spec and reverts back to using its own invented defaults, at least in the case of the "ID" columns.
You can try this on your own: import an worksheet Excel with at least one column header name ending with "ID" ("OrderID", "User ID", or just plain "ID"). During the process, be sure to set "Indexed" to No for those columns. Execute the import and check "Save import steps" in the final dialog window. If you inspect the resulting table design, you will see there is no index on the field(s) in question. Then delete the table, find the saved import and execute it again. This time, those fields will be set as Indexed in the table design, even though the XML still says no index.
I was pulling my hair out until I discovered what was going on, comparing the XML I built from scratch with examples created through the Access tool.
I used Mike Hansen's solution, it is great. I modified his solution in one point, instead of replacing parts of the string I modified the XML-attribute. Maybe it is too much of an effort when you can modify the string but anyway, here is my solution for that.
This could easily be further modified to change the table etc. too, which is very nice imho.
What was helpful for me was a helper sub to write the XML to a file so I could check the structure and content of it:
Sub writeStringToFile(strPath As String, strText As String)
'#### writes a given string into a given filePath, overwriting a document if it already exists
Dim objStream
Set objStream = CreateObject("ADODB.Stream")
objStream.Charset = "utf-8"
objStream.Open
objStream.WriteText strText
objStream.SaveToFile strPath, 2
End Sub
The XML of an/my ImportExportSpecification for a table with 2 columns looks like this:
<?xml version="1.0"?>
<ImportExportSpecification Path="mypath\mydocument.xlsx" xmlns="urn:www.microsoft.com/office/access/imexspec">
<ImportExcel FirstRowHasNames="true" AppendToTable="myTableName" Range="myExcelWorksheetName">
<Columns PrimaryKey="{Auto}">
<Column Name="Col1" FieldName="SomeFieldName" Indexed="NO" SkipColumn="false" DataType="Double"/>
<Column Name="Col2" FieldName="SomeFieldName" Indexed="NO" SkipColumn="false" DataType="Text"/>
</Columns>
</ImportExcel>
</ImportExportSpecification>
Then I wrote a function to modify the path. I left out error-handling here:
Function modifyDataSourcePath(strNewPath As String, strXMLSpec As String) As String
'#### Changes the path-name of an import-export specification
Dim xDoc As MSXML2.DOMDocument60
Dim childNodes As IXMLDOMNodeList
Dim nodeImExSpec As MSXML2.IXMLDOMNode
Dim childNode As MSXML2.IXMLDOMNode
Dim attributesImExSpec As IXMLDOMNamedNodeMap
Dim attributeImExSpec As IXMLDOMAttribute
Set xDoc = New MSXML2.DOMDocument60
xDoc.async = False: xDoc.validateOnParse = False
xDoc.LoadXML (strXMLSpec)
Set childNodes = xDoc.childNodes
For Each childNode In childNodes
If childNode.nodeName = "ImportExportSpecification" Then
Set nodeImExSpec = childNode
Exit For
End If
Next childNode
Set attributesImExSpec = nodeImExSpec.Attributes
For Each attributeImExSpec In attributesImExSpec
If attributeImExSpec.nodeName = "Path" Then
attributeImExSpec.Value = strNewPath
Exit For
End If
Next attributeImExSpec
modifyDataSourcePath = xDoc.XML
End Function
I use this in Mike's code before the newSpec is executed and instead of the replace statement. Also I write the XML-string into an XML-file in a location relative to the database but that line is optional:
Set myNewSpec = CurrentProject.ImportExportSpecifications.item("TemporaryImport")
myNewSpec.XML = modifyDataSourcePath(myPath, myNewSpec.XML)
Call writeStringToFile(Application.CurrentProject.Path & "\impExpSpec.xml", myNewSpec.XML)
myNewSpec.Execute