How to remove long text format "#" (MS Access) - ms-access

I'm working with access office 365 MSO.
While importing excel files into access, sometimes long text columns will be assigned with the format "#". This somehow can lead to truncate the content. Currently I manually have to remove this "#" symbol, however the goal would be, to have a VBA code which would remove all "#" for long text columns, for all existing tables inside the DB.
I found this post Change column data type and format, however my knowledge of VBA is not sufficient to solve the issue. Could someone help?
Example of a long text column with format "#"

Place code in a procedure in general module and run it there or call from another procedure.
Sub DelFmt()
Dim def As DAO.TableDef
Dim fld As DAO.Field
Dim prpName As String
prpName = "Format"
For Each def In CurrentDb.TableDefs
If Not def.name Like "?Sys*" And Not def.name Like "f*" Then
For Each fld In def.Fields
On Error Resume Next
fld.Properties(prpName) = "#"
If Err.Number <> 3270 Then
fld.Properties.Delete prpName
End If
Next
End If
Next
End Sub

Related

Importing thousands of spreadsheets into Access Database table using VBA

I have created this process by lifting code from this (and some other) sites, and it worked like a charm when I tested it, but when I deployed it, it crashed hard... I am novice when it come to VBA and having trouble finding appropriate solution so thought I will ask for help.
Use Case
Accountant receives 100+ spreadsheets per day(!) from employees in the field as a form of required reporting. Before I got involved, 3 accountants would open each spreadsheet received via e-mail and copy/paste certain cell contents into a "master" spreadsheet that will be used for reconciliation at the end of the month. Needless to say, this has become, let's say, inefficient.
What I did
I created an Access DB and used TransferSpreadsheet method to import data. There are only 11 cells that we need imported from each spreadsheet, so I modified spreadsheets that field employees use to pull all this data into a hidden tab, where all data is in one row and all row goes into one table in Access. As I mentioned, when I and accountants tested the solution, it worked beautifully.
What Broke
First issue was that people in a field did not have same versions MS Office, and some used OpenOffice instead and we would get errors when trying to import some spreadsheets. However, since my simple solution was built for "prefect path" only, it was impossible to identify which spreadsheets failed, especially, when there are 2000+ of them sitting in a folder.
What I would like to be able to do
Short-term, until I have time to master VBA, I would love to add some sort of error handler. Or even if after import, "good" spreadsheets would be sent to one folder, and "bad" ones to another. From my experience,about 80% of reports import fine. Once it loops through the whole folder, accountants can check "failed imports" folder and enter these manually. My questions to you, Access VBA experts, is this doable and would be a reasonable solution? If so, can you please direct me to it?
Below is my current code that I adapted from the internets. Thank you for all your help!
Function DoImport()
Dim strPathFile As String
Dim strFile As String
Dim strPath As String
Dim blnHasFieldNames As Boolean
Dim intWorksheets As Integer
Dim strWorksheets(1 To 1) As String
' the number of worksheets to be imported
' from each EXCEL file (this code assumes that each worksheet
' with the same name is being imported into a separate table
' for that specific worksheet name)
Dim strTables(1 To 1) As String
' worksheet names ;
' add / delete code lines so that there is one code line for
' each worksheet that is to be imported from each workbook file
strWorksheets(1) = "Data"
strTables(1) = "my_table"
' Change this next line to True if the first row in EXCEL worksheet
' has field names
blnHasFieldNames = True
'update the path to where the Excel files to be imported are
strPath = "\mypathhere\"
' the number of worksheets to be imported
' from each EXCEL file
For intWorksheets = 1 To 1
strFile = Dir(strPath & "*.xlsm")
Do While Len(strFile) > 0
strPathFile = strPath & strFile
'MsgBox strPathFile
DoCmd.TransferSpreadsheet acImport, acSpreadsheetTypeExcel12Xml, strTables(intWorksheets), strPathFile, blnHasFieldNames, strWorksheets(intWorksheets) & "$"
strFile = Dir()
Loop
Next intWorksheets
End Function
This is off the top of my head (so there may be sytax errors) but the idea is to set the error handling to jump to code that saves the filename and then jump back into the process:
ON ERROR GOTO IMPORT_ERROR
For intWorksheets = 1 To 1
strFile = Dir(strPath & "*.xlsm")
Do While Len(strFile) > 0
strPathFile = strPath & strFile
'MsgBox strPathFile
DoCmd.TransferSpreadsheet acImport, acSpreadsheetTypeExcel12Xml, strTables(intWorksheets), strPathFile, blnHasFieldNames, strWorksheets(intWorksheets) & "$"
strFile = Dir()
GetNextFile:
Loop
Next intWorksheets
EXIT FUNCTION
IMPORT_ERROR:
'ADD CODE HERE TO HANDLE ERROR
ON ERROR GOTO IMPORT_ERROR
GOTO GetNextFile
End Function

How can I find whether VBA code is called in an Access database?

I'm working with a legacy Access database that has a front-end and a good amount of VBA code.
The goal is to either replace the tool with a purchased product or a web application (one day), and while I'm in making bug/fiscal year fixes, I'd like to do a bit of cleanup if I can.
Is it possible to determine if subroutines and functions are used by the application (so I can remove those that are no longer used)?
I know I can export the modules and class objects, but I'm not seeing an option to easily check the actual forms.
Do I have to throw Debug.Print or breakpoints and then just bounce around, or search the forms individually, or is there a better way?
MZTools does this.
MZ-Tools 3.0 is a freeware add-in for Visual Basic 6.0, Visual Basic
5.0 and the Visual Basic For Applications editor (provided by a VBA-enabled application such as those in Office 2000-2013 32-bit,
except Office 64-bit) which adds many productivity features to the
IDE.
[No affiliation.]
The following will search all queries (including ones in RecordSource and Rowsource):
Public Sub CheckQueries(ByVal str As String)
Dim qu As QueryDef
For Each qu In CurrentDb.QueryDefs
If InStr(qu.SQL, str) > 0 Then
Debug.Print qu.Name
End If
Next
End Sub
OK, this answer will require some work and programming. I only have the beginnings of the code you'll need, so you'll have to do some research, along with some trial & error.
When you're working in the VBA editor within Access, it's called the VBE. This holds all the code in all the modules forms, & reports. The debug.print lines are what you're after.
If you go line by line and save it to a table, along with the procedure name & and object name (forms & reports), and save it to a table, you can then do a no match query to see what procedures never get called (they're listed as a procedure, but not in any code line.
Expect this to take a few hours of your time to get right. But once you do, you'll have a nice tool.
Function GetVBEDeatils2()
Dim vbProj As VBProject
Dim vbComp As VBComponent
Dim vbMod As CodeModule
Dim sProcName As String
Dim pk As vbext_ProcKind
Dim iCounter As Long
Dim ProcLines As Long
For Each vbProj In Application.VBE.VBProjects 'Loop through each project
For Each vbComp In vbProj.VBComponents 'Loop through each module
Set vbMod = vbComp.CodeModule
iCounter = 1
Do While iCounter < vbMod.CountOfLines 'Loop through each procedure
sProcName = vbMod.ProcOfLine(iCounter, pk)
If sProcName <> "" Then
Debug.Print vbMod.Lines(iCounter, vbMod.ProcCountLines(sProcName, pk))
Debug.Print
iCounter = iCounter + vbMod.ProcCountLines(sProcName, pk)
Else
iCounter = iCounter + 1
End If
Loop
Next vbComp
Next vbProj
Set vbMod = Nothing
End Function
Use the built-in Documenter tool. This is easier than poking open the VBE editor (at least if you're new to that). And easier than using MZ-Tools, although it is a TERRIFIC tool.
See this post for specifics.

VBA Executing CODE from a ComboBox

I have a very complex process that involves downloading a number of files from different shares, concatenating those files into working tables, manipulating and calculating related information, and then exporting specific fields (and calculations) as reports into a number of Excel workbooks.
I have this process coded so that I can click one button and the entire process will execute end to end. I have a series of text boxes that function as 'indicators' (red - this part failed, green - this part succeeded). As you can imagine, the code for the entire process is HUGE (32 pages when copied into MSWord) and difficult to weed through when I have a problem.
I got it into my mind that I wanted to put the code into a table so that it was much more modular and easier to deal with. I have setup a combo box with the action that I want to take and a second combo box with the report/file/object that I want to work with (ie Delete - Table 2, Acquire - File 1, Export - Report 4). I have been successful at creating the SQL statement to do simple things like del * from tbl_test and execute that from the combo boxes without any issue.
What I need to know is if there is a way to put what is essentially a code snippet into the table (memo field) and then have that vba code execute when I select the matching combos.
IE the code for 'Acquire - File1' is completely VBA code; it maps a network drive, locates the file, downloads the file, and moves it to a directory.
IE the code for 'Scrub - tblMain_Part1' is a combination of vba and sql code; it checks for the existence of a file (vba), if it finds it, it deletes a portion of the main table (sql) and appends the contents of the file it finds (sql), then it updates the monitor to indicate that it is completed (vba). If the file is not found, it changes the monitor box to red and updates a command button caption (vba)
I am NOT a genius with vba, but I hold my own. The thought process I had was that if I can essentially get the code broken into managable chunks in the table, I could call the code smippets in order if I want to run the entire process, or I could just re-execute portions of the code as needed by selecting the action and report/file/object combination.
Any thoughts/ideas are appreciated.
I think it would be best to split the code into Subs. The table you loop through would have a Sub-Name field and a blnSuccess field. Your code would loop though the table running each sub and then updating blnSuccess based on any errors you receive. This would give you queryable result set when you try to see what happened.
Consider using macros. You shouldn't need a table. Also, consider moving your hard-coded SQL to queries.
I think that you shouldn't use a table, just create a module with different subs for each operation. On your button event, after the combo selections, I would do a case statement.
dim strOperation as string
strOperation = me!selectionOne
Select Case strOperation
Case "delete": deleteTable(me!selectionTwo)
Case "export": export(me!selectionTwo)
case "acquire": acquire(me!selectionTwo)
End Select
Of course, you'd have your acquire, delete, and export methods written in a module and have whatever parameters you need for each operation there.
This is just one idea of many that you could use to approach this.
I was going to edit the original answer but this seems to be off on a different tack....
I think it would be best to split the code into functions that return a string if there is an error. The table you loop through would have a strFunction,strError and strObject fields. Your code would loop though the table running each function based on the case statement while passing the strObject as a string and then updating strError based on any errors you receive. You could query the table after this process to see which records have errors in them.
If the button is called cmdRunAll here is the code for it.
Private Sub cmdRunAll_Click()
On Error GoTo ErrHandler
Dim rst As DAO.Recordset
Set rst = CurrentDb.OpenRecordset("tblCode", dbOpenDynaset, dbSeeChanges)
If Not rst.EOF Then
With rst
.MoveFirst
Do While Not .EOF
.Edit
Select Case !strFunction
Case "fExport"
!strError = fExport(!strObject)
End Select
.Update
.MoveNext
Loop
End With
End If
rst.Close
Set rst = Nothing
MsgBox "Processes complete"
Exit Sub
ErrHandler:
Debug.Print Err.Description & " cmdRunAll_Click " & Me.Name
Resume Next
End Sub
Here is a simple sample function
Public Function fExport(strTable As String) As String
On Error GoTo ErrHandler
Dim strError As String
strError = ""
DoCmd.TransferText acExportDelim, , strTable, "C:\users\IusedMyUserNameHere\" & strTable & ".txt"
fExport = strError
Exit Function
ErrHandler:
strError = Err.Description
Resume Next
End Function

Exporting data from MS Access to Excel using VBA

I have a table in MS Access, which has the following data to be exported to excel
Release numbers
Test cases
Results
After exporting to Excel I want to have distinct release numbers as rows starting from A2 and distinct test case name as columns starting from B1. There might be couple thousands records. Then each cell will be set to result tag. Additionally will need some fancy coloring/bordering stuff.
The question - is it possible to do this using VBA in Access and if yes what is the way to go? Any hint, sample, example, resource would be appreciated... I've googled but the most thing I came accross is DoCmd.TransferSpreadsheet or DoCmd.OutputTo which I believe will not do what I want. Saw some examples with CreateObject("Excel.Application") but not sure what are limitations and performance using this way.
I don't know if it would work for your case, but you might try adding the VBA code to an Excel document rather than the Access database. Then you could refresh the data from the Excel file and add the formatting there much easier. Here is one example:
http://www.exceltip.com/st/Import_data_from_Access_to_Excel_%28ADO%29_using_VBA_in_Microsoft_Excel/427.html
(Or see other examples at http://www.exceltip.com/exceltips.php?view=category&ID=213)
Again, it may not work for your case, but it may be an option to consider. Essentially, instead of pushing from Access, you would pull from Excel.
Yes, there are many cases when the DoCmd.TransferSpreadsheet command is inadaquate.
The easiest way is to reference the Excel xx.x Object model within Access (Early Binding). Create and test your vba export function that way. Then once you are satisfied with your output, remove the Excel object model reference, then change your objects to use use Late Binding using CreateObject. This allows you to easily have other machines that are using different versions of Excel/Access to use it just the same.
Here is a quick example:
Sub ExportRecordsetToExcel(outputPath As String, rs As ADODB.Recordset)
'exports the past due report in correct formattig to the specified path
On Error GoTo handler:
Const xlUP As Long = -4162 'excel constants if used need to be referenced manually!
Dim oExcel As Object
Dim oBook As Object
Dim oSheet As Object
Dim row As Long
If rs.BOF And rs.EOF Then
Exit Sub 'no data to write
Else
rs.MoveFirst
End If
row = 1
Set oExcel = CreateObject("Excel.Application")
oExcel.Visible = False 'toggle for debugging
Set oBook = oExcel.Workbooks.Add 'default workbook has 3 sheets
'Add data to cells of the first worksheet in the new workbook.
Set oSheet = oBook.worksheets(1)
Do While rs.EOF = False
oSheet.range("A" & row).value = rs.Fields("MyField").value
'increase row
row = row + 1
Loop
oBook.SaveAs (outputPath)
'tidy up, dont leave open excel process
Set oSheet = Nothing
Set oBook = Nothing
oExcel.Quit
Set oExcel = Nothing
Exit Sub
handler:
'clean up all objects to not leave hanging processes
End Sub

Access: How to execute a query and save its result in a report

HI,
I am trying to write a query in vba and to save its result in a report.
I am a beginner. this is what i have tried
can somebody correct me
Dim cn As New ADODB.Connection, rs As New ADODB.Recordset
Dim sql As String
Set cn = CurrentProject.Connection
sql = "Select * from table1 where empno is 0"
rs.Open sql, cn
While Not rs.EOF
' here i think i should save the result in a report but i am not sure how
rs.MoveNext
Wend
rs.Close
cn.Close
Set rs = Nothing
Set cn = Nothing
Also how do i change this query to run this on all tables in a database
IF you are wanting to create a report using MS Access's report generator, you will have to use a Query Object (there might be a way to trick MS Access into running it off of your record set, but it's probably not worth your effort).
You can create the Query Object on the "Database" window. Click the Query button in the objects list, and then click on New. In the resulting editor you can create the query graphically or if you prefer with SQL. Save the query and give it a meaning full name.
Similarly the report can be created on the "Database" window. Click on the Report button and then on New. In the resulting wizard, you'll link the report to the query you just created.
Update: As D.W. Fenton said, you can embed the query right within the Report Object without creating a separate Query Object. My preference is to create one anyway.
The problem with this method is you would have to create a separate query and report for each table.
IF you just want to dump the result out to a text file (to read/print later), then you can do it using recordsets like you are in your VBA code. It will look something like this
'...
dim strFoo as string
dim strBar as string
'...
if not rs.bof then
rd.MoveFirst
end if
While Not rs.EOF
strFoo = rs("foo") 'copy the value in the field
'named "foo" into strFoo.
strBar = rs("bar")
'... etc. for all fields you want
'
'write out the values to a text file
'(I'll leave this an exercise for the reader)
'
rs.MoveNext
Wend
'...
Parsing all of the tables can be done in a loop something like this:
dim strTableName as string
dim db As Database
'...
Set db = CurrentDb
db.TableDefs.Refresh
For Each myTable In db.TableDefs
If Len(myTable.Connect) > 0 Then
strTableName = myTable.Name
'...
'Do something with the table
'...
End If
Next
set db = nothing
=======================UPDATE=======================
It is possible to run an MS-Access Report from a record set. To repease what I said to tksy's question
From Access Web you can use the "name" property of a recordset. You resulting code would look something like this:
In the report
Private Sub Report_Open(Cancel As Integer)
Me.RecordSource = gMyRecordSet.Name
End Sub
In the calling object (module, form, etc.)
Public gMyRecordSet As Recordset
'...
Public Sub callMyReport()
'...
Set gMyRecordSet = CurrentDb.OpenRecordset("Select * " & _
"from foo " & _
"where bar='yaddah'")
DoCmd.OpenReport "myReport", acViewPreview
'...
gMyRecordSet.Close
Set gMyRecordSet = Nothing
'...
End Sub
Q.E.D.
Normally you would design the report based on a data source. Then after your report is done and working properly you use VBA to display or save the report.
To run this for each table in the database, I'd suggest writing a function that looped through CurrentData.AllTables(i) and then called your function above in each iteration
Hope this helps
If you want to simply view the results, you can create a query. For example, here is some rough, mostly untested VBA:
Sub ViewMySQL
Dim strSQL as String
Dim strName As String
'Note that this is not sensible in that you
'will end up with as many queries open as there are tables
For Each tdf In CurrentDB.TableDefs
If Left(tdf.Name,4)<>"Msys" Then
strName = "tmp" & tdf.Name
strSQL = "Select * from [" & tdf.Name & "] where empno = 0"
UpdateQuery strName, strSQL
DoCmd.OpenQuery strName, acViewNormal
End If
Next
End Sub
Function UpdateQuery(QueryName, SQL)
If IsNull(DLookup("Name", "MsysObjects", "Name='" & QueryName & "'")) Then
CurrentDb.CreateQueryDef QueryName, SQL
Else
CurrentDb.QueryDefs(QueryName).SQL = SQL
End If
UpdateQuery = True
End Function
You may also be interested in MDB Doc, an add-in for Microsoft Access 97-2003 that allows you to document objects/properties within an Access database to an HTML file.
-- http://mdbdoc.sourceforge.net/
It's not entirely clear to me what you want to do. If you want to view the results of SQL statement, you'd create a form and set its recordsource to "Select * from table1 where empno is 0". Then you could view the results one record at a time.
If that's not what you want, then I'm afraid I just don't have enough information to answer your question.
From what you have said so far, I don't see any reason why you need VBA or a report, since you just want to view the data. A report is for printing, a form is for viewing and editing. A report is page-oriented and not that easy to navigate, while a form is record-oriented, and allows you to edit the data (if you want to).
More information about what you want to accomplish will help us give you better answers.
Had the same question. just use the clipboard!
select the query results by click/dragging over all field names shown
press ctrl-c to copy to windows clipboard
open a blank document in word and click inside it
press ctrl-v to paste from clipboard.