User-Specific WorkTables: How to handle MakeTable queries?

  • Thread starter Thread starter (PeteCresswell)
  • Start date Start date
P

(PeteCresswell)

I put this up on comp.databases.ms-access, but no takers...
=============================================================
When writing to a work DB under C:\Documents and
Settings\[UserName]...., what is the best way to handle MakeTable
queries?

The only approaches I can think of are:
-------------------------------------------------------------------
1) Don't use MakeTable queries. Instead, create a work table in the
desired Work DB and replace the MakeTable query with an Append
query that goes through an ODBC link to the created work table.


2) Every time the app opens, iterate through all the queries, try to
parse out the "IN" statement in each Append query and modify
it accordingly.


3) As above, but update some sort of property that determines the
target DB. But what property?


4) Stop using QueryDefs for MakeTable queries and concoct
inline SQL to do the same job.
----------------------------------------------------------------------


Seems like #2 is just a bug waiting to happen - some unforeseen syntax
would blow it up. There's also the issue of bloating the DB every time the
QueryDef is updated.

Looks like #3 is not doable.

For #4, I'm not currently into inline SQL for documentation readability
reasons and, probably, pure habit. OTOH, it's not a religious issue
with me.... I *could* mend my ways...


If #3 really is not doable, it seems like #1 or #4 is the way to go.


Anybody else been here?
 
Per RobFMS:
I am a little lost here. What is the goal you are trying to accomplish?

I want to get into compliance with the MS standard (that I learned about via
hearsay... but which seems pretty clear..) that an application's
non-persistent/"temp"/"work" files should be written under the user's personal
"Documents and Settings" directory and not to something else like C:\Temp.
e.g. "C:\Documents and Settings\Kolon Skorupski\Local Settings\..."

So each time the app creates a work table, it's location will be different
depending on the user's name.

Creating work tables directly is no problem because it's done with inline code
and I just create the DB in the right place and either create a link or alter an
existing link.

Creating work tables via MakeTable queries is where I'm groping for the best
solution.

To save somebody from looking up the OP:
======================================================================

The only approaches I can think of are:
-------------------------------------------------------------------
1) Don't use MakeTable queries. Instead, create a work table in the
desired Work DB and replace the MakeTable query with an Append
query that goes through an ODBC link to the created work table.


2) Every time the app opens, iterate through all the queries, try to
parse out the "IN" statement in each Append query and modify
it accordingly.


3) As above, but update some sort of property that determines the
target DB. But what property?


4) Stop using QueryDefs for MakeTable queries and concoct
inline SQL to do the same job.
----------------------------------------------------------------------


Seems like #2 is just a bug waiting to happen - some unforeseen syntax
would blow it up. There's also the issue of bloating the DB every time the
QueryDef is updated.

Looks like #3 is not doable.

For #4, I'm not currently into inline SQL for documentation readability
reasons and, probably, pure habit. OTOH, it's not a religious issue
with me.... I *could* mend my ways...


If #3 really is not doable, it seems like #1 or #4 is the way to go.

======================================================================
 
Pete:

In a slightly different context to yours but here's a function of mine from
a Bill of Materials application which creates a temporary database and then
creates temporary tables in it using DDL statements via DAO. I guess this
would be in your category 4:

Function ExplodeParts(Assembly As String) As Boolean

' creates parts explosion with aggregated quantities in BoM table.
' accepts name of table with column headings MajorPartNum,
' MinorPartNum and Quantity where MajorPartNum and MinorPartNum
' both reference primary key PartNum of Parts table.
' returns True if parts explosion sucessfully computed, False otherwise.

Dim dbs As DAO.Database, dbsTemp As DAO.Database
Dim qdf As DAO.QueryDef, tdf As DAO.TableDef
Dim varFld As Variant

Dim strSQL As String, strSQL1 As String, strSQL2 As String
Dim strSQL3 As String, strSQL4 As String, strSQL5 As String
Dim strSQL6 As String, strSQL7 As String, strSQL8 As String
Dim strSQL9 As String

Dim n As Integer

Set dbs = CurrentDb

' create temporary database in same folder as current database
' or return reference to database if already exists
strTempDb = Left$(dbs.Name, Len(dbs.Name) - Len(Dir(dbs.Name))) &
"BoMTemp.mdb"
On Error Resume Next
Set dbsTemp = CreateDatabase(strTempDb, dbLangGeneral)
If Err <> 0 Then
Set dbsTemp = OpenDatabase(strTempDb)
End If
On Error GoTo Err_Handler

' create BoM table in temporary database if doesn't exist
strSQL = "CREATE TABLE BoM (MajorPartNum LONG NOT NULL, " & _
"MinorPartNum LONG NOT NULL, Quantity LONG NOT NULL, " & _
"CONSTRAINT MajorMinor PRIMARY KEY (MajorPartNum, MinorPartNum) )"
On Error Resume Next
dbsTemp.Execute (strSQL)
On Error GoTo Err_Handler

' create BoM_Temp table in temporary database.
' note that this one has no constraint as it will be
' necessary to add duplicates of major/minor part number
' values in separate rows
strSQL = "CREATE TABLE BoM_Temp (MajorPartNum LONG NOT NULL, " & _
"MinorPartNum LONG NOT NULL, Quantity LONG NOT NULL)"
dbsTemp.Execute (strSQL)

' check if link to BoM_Temp table exists and if not create link
On Error Resume Next
Set tdf = dbs.TableDefs("BoM_Temp")
If Err <> 0 Then
DoCmd.TransferDatabase acLink, "Microsoft Access", strTempDb,
acTable, "BoM_Temp", "BoM_Temp"
Else
varFld = tdf.Fields(0)
If Err <> 0 Then
' refresh link if curent link invalid
tdf.Connect = ";DATABASE=" & strTempDb
tdf.RefreshLink
End If
End If
Err.Clear

' check if link to BoM table exists and if not create link
Set tdf = dbs.TableDefs("BoM")
If Err <> 0 Then
DoCmd.TransferDatabase acLink, "Microsoft Access", strTempDb,
acTable, "BoM", "BoM"
Else
varFld = tdf.Fields(0)
If Err <> 0 Then
' refresh link if current link invalid
tdf.Connect = ";DATABASE=" & strTempDb
tdf.RefreshLink
End If
End If
Err.Clear
On Error GoTo Err_Handler

' copy Assembly table to temporary database
DoCmd.TransferDatabase acExport, "Microsoft Access", strTempDb, acTable,
Assembly, Assembly
' copy Parts table to temporary database
DoCmd.TransferDatabase acExport, "Microsoft Access", strTempDb, acTable,
"Parts", "Parts"

' empty BoM table
strSQL = "DELETE * FROM BoM"
dbsTemp.Execute (strSQL)

' add first level data to BoM_Temp table by appending
' all rows from Assembly table
strSQL = "INSERT INTO BoM_Temp " & _
"SELECT " & Assembly & ".* " & _
"FROM " & Assembly
Set qdf = dbsTemp.CreateQueryDef("")
qdf.SQL = strSQL
qdf.Execute

' attempt to add second level by adding second instance
' of Assembly table to query
strSQL1 = "INSERT INTO BoM_Temp ( MajorPartNum, MinorPartNum, Quantity ) "
strSQL2 = "SELECT PS1.MajorPartNum, PS2.MinorPartNum, "
strSQL3 = "SUM(PS1.Quantity*PS2.Quantity"
strSQL4 = ") "
strSQL5 = "FROM " & Assembly & " AS PS1, " & Assembly & " AS PS2"
strSQL6 = " WHERE PS1.MinorPartNum = PS2.MajorPartNum "
strSQL7 = ""
strSQL8 = "GROUP BY PS1.MajorPartNum, PS"
strSQL9 = "2.MinorPartNum"


strSQL = strSQL1 & strSQL2 & strSQL3 & strSQL4 & strSQL5 & _
strSQL6 & strSQL7 & strSQL8 & strSQL9
Set qdf = dbsTemp.CreateQueryDef("")
qdf.SQL = strSQL
qdf.Execute

' don't attempt to add any more levels if no second level added
If qdf.RecordsAffected > 0 Then
' add further levels until no more to be added
n = 2
Do While True
n = n + 1

' amend SQL to add further instance of Assembly table to queries
strSQL2 = "SELECT PS1.MajorPartNum, PS" & n & ".MinorPartNum, "
strSQL3 = strSQL3 & "*PS" & n & ".Quantity"
strSQL5 = strSQL5 & "," & Assembly & " AS PS" & n
strSQL7 = strSQL7 & " AND PS" & (n - 1) & ".MinorPartNum = PS" &
n & ".MajorPartNum "
strSQL9 = n & ".MinorPartNum"

' add next level
strSQL = strSQL1 & strSQL2 & strSQL3 & strSQL4 & strSQL5 & _
strSQL6 & strSQL7 & strSQL8 & strSQL9
Set qdf = dbs.CreateQueryDef("")
qdf.SQL = strSQL
qdf.Execute

' refill BoM table if no more levels added
If qdf.RecordsAffected = 0 Then
Exit Do
End If
Loop
End If

' append aggregated data to BoM table
strSQL = "INSERT INTO BoM ( MajorPartNum, MinorPartNum, Quantity ) " & _
"SELECT BoM_Temp.MajorPartNum, BoM_Temp.MinorPartNum, " & _
"SUM(BoM_Temp.Quantity) " & _
"FROM BoM_Temp " & _
"GROUP BY BoM_Temp.MajorPartNum, BoM_Temp.MinorPartNum"
dbsTemp.Execute (strSQL)

ExplodeParts = True

Exit_Here:
On Error Resume Next

' delete BoM_Temp table in temporary database
strSQL = "DROP Table BoM_Temp"
dbsTemp.Execute (strSQL)

' delete Parts table in temporary database
strSQL = "DROP Table Parts"
dbsTemp.Execute (strSQL)

' delete Assembly table in temporary database
strSQL = "DROP Table " & Assembly
dbsTemp.Execute (strSQL)

Exit Function

Err_Handler:
MsgBox Err.Description & " (" & Err.Number & ")", vbExclamation, "Error"
ExplodeParts = False
Resume Exit_Here

End Function

Ken Sheridan
Stafford, England

(PeteCresswell) said:
I put this up on comp.databases.ms-access, but no takers...
=============================================================
When writing to a work DB under C:\Documents and
Settings\[UserName]...., what is the best way to handle MakeTable
queries?

The only approaches I can think of are:
-------------------------------------------------------------------
1) Don't use MakeTable queries. Instead, create a work table in the
desired Work DB and replace the MakeTable query with an Append
query that goes through an ODBC link to the created work table.


2) Every time the app opens, iterate through all the queries, try to
parse out the "IN" statement in each Append query and modify
it accordingly.


3) As above, but update some sort of property that determines the
target DB. But what property?


4) Stop using QueryDefs for MakeTable queries and concoct
inline SQL to do the same job.
----------------------------------------------------------------------


Seems like #2 is just a bug waiting to happen - some unforeseen syntax
would blow it up. There's also the issue of bloating the DB every time the
QueryDef is updated.

Looks like #3 is not doable.

For #4, I'm not currently into inline SQL for documentation readability
reasons and, probably, pure habit. OTOH, it's not a religious issue
with me.... I *could* mend my ways...


If #3 really is not doable, it seems like #1 or #4 is the way to go.


Anybody else been here?
 
(PeteCresswell) said:
I put this up on comp.databases.ms-access, but no takers...
=============================================================
When writing to a work DB under C:\Documents and
Settings\[UserName]...., what is the best way to handle MakeTable
queries?

The only approaches I can think of are:
-------------------------------------------------------------------
1) Don't use MakeTable queries. Instead, create a work table in the
desired Work DB and replace the MakeTable query with an Append
query that goes through an ODBC link to the created work table.


2) Every time the app opens, iterate through all the queries, try to
parse out the "IN" statement in each Append query and modify
it accordingly.


3) As above, but update some sort of property that determines the
target DB. But what property?


4) Stop using QueryDefs for MakeTable queries and concoct
inline SQL to do the same job.
----------------------------------------------------------------------


Seems like #2 is just a bug waiting to happen - some unforeseen syntax
would blow it up. There's also the issue of bloating the DB every
time the QueryDef is updated.

Looks like #3 is not doable.

For #4, I'm not currently into inline SQL for documentation
readability reasons and, probably, pure habit. OTOH, it's not a
religious issue with me.... I *could* mend my ways...


If #3 really is not doable, it seems like #1 or #4 is the way to go.


Anybody else been here?

If I understand you correctly, I use a simple class module I wrote to

(a) Create a temporary work database in the user's Temp folder (as
returned by the Windows GetTempPath() API function),

(b) Create a work table in that database, modeled on an existing
"template" table in the current database,

(c) Create a linked table in the current database, pointing to the
work table,

(d) Delete the linked table when requested, or when the class object
is destroyed, and

(e) Delete the work database when the class object is destroyed.

You're welcome to the code, if you like; it's very simple.
 
Per RobFMS:
Maybe its better to ask this question: What is YOUR definition of a Work
Table?

Is this a table within Access or is this an entire .MDB?

An entire .MDB that does not persist once the application has been closed.

I've seen work tables created within the front end, but it always seemed like a
bad idea to me - bloat and all that.
 
Per Dirk Goldgar:
If I understand you correctly, I use a simple class module I wrote to

(a) Create a temporary work database in the user's Temp folder (as
returned by the Windows GetTempPath() API function),

(b) Create a work table in that database, modeled on an existing
"template" table in the current database,

(c) Create a linked table in the current database, pointing to the
work table,

(d) Delete the linked table when requested, or when the class object
is destroyed, and

(e) Delete the work database when the class object is destroyed.

You're welcome to the code, if you like; it's very simple.

That's what I'm doing now - although I just use a module ("basWorkTables") and
call it's routines instead of creating a Class.

The hitch is MakeTable queries - which have the path to the target DB embedded
in their SQL.
 
Dear Dirk:
You're welcome to the code, if you like; it's very simple.

Ha! *You* post the code, Dirk... *I'll* tell you if it's very simple or not!
<g>

Cheers!
Fred
 
(PeteCresswell) said:
Per Dirk Goldgar:

That's what I'm doing now - although I just use a module
("basWorkTables") and call it's routines instead of creating a Class.

The hitch is MakeTable queries - which have the path to the target DB
embedded in their SQL.

I don't think I understand what you're doing. Where do the make-table
queries come in? Using my class module, for example, you never run a
make-table query to create a table in the work database. You just tell
it to create a table modeled on a template table in your database, and
it uses DoCmd.TransferDatabase to copy the structure of that table to
the work database. The template table could be a real, production table
in your database, or it could be an empty table that you have previously
created just to serve as a template -- that's the way I've always done
it.

If you don't want to do that, I'd be inclined to build the SQL for a
make-table on the fly, so as to be able to build in the path to the
source or target database as I choose. I don't see why you are
resistant to the idea of creating the SQL dynamically.
 
Fred Boer said:
Ha! *You* post the code, Dirk... *I'll* tell you if it's very simple
or not! <g>

Do you want it? It's nothing special, but it has served my purposes.
 
Dear Dirk:

Well, I was being a bit facetious, but I *do* learn from looking at good
code examples, so, yes, please, if you'd be so kind! :)

Fred
 
You could put the temp MDB in C:\Documents and Settings\All
Users\Application Data\something
 
Per Joan Wild:
You could put the temp MDB in C:\Documents and Settings\All
Users\Application Data\something

That's what I'm doing.

My problem is what do about the MakeTable queries.
 
Per Dirk Goldgar:
I don't think I understand what you're doing. Where do the make-table
queries come in? Using my class module, for example, you never run a
make-table query to create a table in the work database. You just tell
it to create a table modeled on a template table in your database, and
it uses DoCmd.TransferDatabase to copy the structure of that table to
the work database. The template table could be a real, production table
in your database, or it could be an empty table that you have previously
created just to serve as a template -- that's the way I've always done
it.

That's basically what I already do for all other situations.

Sounds to me like my Option #1 (Don't use MakeTable queries) is the
way to go.

If you don't want to do that, I'd be inclined to build the SQL for a
make-table on the fly, so as to be able to build in the path to the
source or target database as I choose. I don't see why you are
resistant to the idea of creating the SQL dynamically.

My superficial rationale is that inline SQL detracts from the readability of the
application. Instead of instantly comprehending "qryFundMonthlyReturns_Create"
and being able to see/modify the SQL graphically, the maintenance programmer has
to slog through the SQL.

But in reality, I think it's more a matter of habit than anything else - and I'd
change in a New York minute and never look back if I thought it was necessary.
For maintenance purposes, I could even create new class of query: "zmqry..." for
model queries that contain the JCL used inline...


But I like the create-work-from-model-then-populate-it approach. I don't even
know why the few MakeTable queries that are in this app are there - everything
else uses the copy-model-then-append approach. Also, now that I think about
it, a slight weakness of MakeTable is that you give up some control over the
design of the table. It's largely determined by the source recordset. Indexing
and other stuff can be pre-set in a model table instead of using a bunch of DAO
code to modify the results of a MakeTable.


Basically, I was just trolling for some innovative approach from this great
gathering of minds...
 
Dirk Goldgar said:
You're welcome to the code, if you like; it's very simple.

Since Fred was so importunate, here it is. A whole bunch of lines are
going to be wrapped by the newsreader, and I'll leave it to you to
"unwrap them".

'----- start of module code -----
Option Compare Database
Option Explicit

' Class clsWorkDB creates a temporary work-database and allows the user
to create,
' link to, and manipulate temporary tables in the work database. A new
work database
' is created for each instance of this class. All tables are unlinked
and the work
' database is deleted when that instance is destroyed.

' Copyright 2002, 2003 Dirk Goldgar and DataGnostics. All rights
reserved.
' Permission is granted to use this code in your application, provided
' that the copyright notice remains intact.

' Procedures TempDir and TempFile in this module were written by Terry
Kreft
' and posted for public use. Neither Dirk Goldgar nor DataGnostics
claims
' copyright on these procedures.

Private Declare Function GetTempPath Lib "kernel32" Alias "GetTempPathA"
_
(ByVal nBufferLength As Long, ByVal lpBuffer As String) As Long

Private Declare Function GetTempFileName Lib "kernel32" Alias
"GetTempFileNameA" _
(ByVal lpszPath As String, ByVal lpPrefixString As String, _
ByVal wUnique As Long, ByVal lpTempFileName As String) As Long


Private mdbWorkDB As DAO.Database ' This is the work database we'll be
using.
' We create the database file when
the class
' is instantiated and set this
reference to it.
' When the instance is destroyed, we
delete the
' file.

Private mblnEchoStatus As Boolean ' Should we assume Application.Echo
is on (True) or off?


Private mstrCallWhenEmpty As String ' If not empty, this is the name of
a public
' procedure to be called (via
Application.Run)
' when a call to this class's
DropTable method
' leaves the work database empty of
tables. The
' assumption is that the called
procedure will
' destroy this instance of the
class.

Private mlngSystemTableCount ' When the work database is created,
we set this
' to the number of tables in the
database before
' any user tables have been created.
That way,
' we'll know when the last user
table has been
' deleted.

Public Sub DropWorkTable(TableName As String)

' Drop a table in the work database, and the local table that is
linked to it.

Dim dbCurr As DAO.Database
Dim tdf As DAO.TableDef
Dim strErrMsg As String
Dim strLinkedTable As String
Dim lngError As Long
Dim lngTDFCount As Long

' Make sure that the table whose name we were passed exists as a
linked table in
' the current database, and that it is linked to a table of the same
name in
' the work database.
Set dbCurr = DBEngine(0)(0)
dbCurr.TableDefs.Refresh
On Error Resume Next
Set tdf = dbCurr(TableName)
lngError = Err.Number
On Error GoTo 0

Select Case lngError
Case 0
' The table exists; so far so good. Is it linked to our
work database?
If tdf.Connect <> ";DATABASE=" & mdbWorkDB.Name Then
strErrMsg = "Can't delete work table '" & TableName & _
"' -- this table is not linked to the work
database."
Else
' Just in case, get the source-table name from the
tabledef.
strLinkedTable = tdf.SourceTableName
End If
Case 3265
' Oops, the table doesn't exist.
strErrMsg = "Can't delete work table '" & TableName & _
"' -- this table does not exist."
Case Else
' Some other error occurred, which is going to mess us up.
strErrMsg = "Can't delete work table '" & TableName & _
"' -- error " & lngError & " accessing table in
the current database."
End Select

Set tdf = Nothing

If Len(strErrMsg) > 0 Then
Set dbCurr = Nothing
Err.Raise 5, strErrMsg
Else
' Delete the table from the current database.
dbCurr.TableDefs.Delete TableName
Set dbCurr = Nothing
RefreshDatabaseWindow

' Delete the table from the work database.
With mdbWorkDB.TableDefs
.Delete strLinkedTable
.Refresh
' Capture the updated tabledef count.
lngTDFCount = .Count
End With

' We may have been given the name of a public procedure to
' call when the work database has no more user tables.
If lngTDFCount <= mlngSystemTableCount Then
If Len(mstrCallWhenEmpty) > 0 Then
Application.Run mstrCallWhenEmpty
End If
End If

End If

End Sub

Public Property Let EchoStatus(NewValue As Boolean)

mblnEchoStatus = NewValue

End Property

Public Property Get EchoStatus() As Boolean

EchoStatus = mblnEchoStatus

End Property

Public Property Get Name() As String

Name = mdbWorkDB.Name

End Property

Private Function TempDir() As String

' Return path to system temp directory.

' Written by Terry Kreft.

Dim lngRet As Long
Dim strTempDir As String
Dim lngBuf As Long

strTempDir = String$(255, 0)
lngBuf = Len(strTempDir)

lngRet = GetTempPath(lngBuf, strTempDir)

If lngRet > lngBuf Then
strTempDir = String$(lngRet, 0)
lngBuf = Len(strTempDir)
lngRet = GetTempPath(lngBuf, strTempDir)
End If

TempDir = left(strTempDir, lngRet)

End Function

Private Function TempFile( _
Create As Boolean, _
Optional lpPrefixString As Variant, _
Optional lpszPath As Variant) _
As String

'Creates and/or returns the name of a unique temp file
'
'<Create> determines whether to just return a filename or
'to create the file.
'
'<lpPrefixString> defines the first three letters of the
'temp filename; if left blank, will use "tmp".
'
'<lpszPath> defines the directory path to the temporary file;
'if left blank, will use the system temp directory setting.

' Written by Terry Kreft.

Dim lpTempFileName As String * 255
Dim strTemp As String
Dim lngRet As Long

If IsMissing(lpszPath) Then
lpszPath = TempDir
End If

If IsMissing(lpPrefixString) Then
lpPrefixString = "tmp"
End If

lngRet = GetTempFileName(lpszPath, lpPrefixString, 0,
lpTempFileName)

strTemp = lpTempFileName

lngRet = InStr(lpTempFileName, Chr$(0))
strTemp = left(lpTempFileName, lngRet - 1)

If Create = False Then
Kill strTemp
Do Until Dir(strTemp) = "": DoEvents: Loop
End If

TempFile = strTemp

End Function


Public Property Let CallWhenEmpty(NewValue As String)

mstrCallWhenEmpty = NewValue

End Property

Private Sub Class_Initialize()

Dim strWorkDBName As String
Dim strWorkDBFolder As String
Dim wrkDefault As Workspace

strWorkDBName = TempFile(False)

' Get default Workspace.
Set wrkDefault = DBEngine.Workspaces(0)

'Create a new temp database
Set mdbWorkDB = wrkDefault.CreateDatabase(strWorkDBName,
dbLangGeneral)

Set wrkDefault = Nothing

mblnEchoStatus = True ' default value for EchoStatus property is
True

' Record the number of tables in the database before no user tables
' have been created. This will be the count of system tables, but
' we have to add 1 to it because another system table,
MSysAccessStorage,
' will be added the first time Access creates a table in the
database.
mlngSystemTableCount = mdbWorkDB.TableDefs.Count + 1

End Sub


Private Sub Class_Terminate()

Dim dbCurr As DAO.Database
Dim tdf As DAO.TableDef
Dim strWorkDBName As String
Dim strConnect As String
Dim lngT As Long

If mdbWorkDB Is Nothing Then
Exit Sub
End If

' Capture the name of the work database before closing it.
strWorkDBName = mdbWorkDB.Name

' Remove all tabledefs in the current database that are linked to
the
' work database.

Set dbCurr = DBEngine(0)(0)
dbCurr.TableDefs.Refresh
strConnect = ";DATABASE=" & strWorkDBName

With dbCurr.TableDefs
For lngT = (.Count - 1) To 0 Step -1
Set tdf = .Item(lngT)
If tdf.Connect = strConnect Then
.Delete tdf.Name
End If
Set tdf = Nothing
Next lngT
End With
Set dbCurr = Nothing

RefreshDatabaseWindow

' Close and destroy the work database object.
mdbWorkDB.Close
Set mdbWorkDB = Nothing

' Erase the work database file.
Kill strWorkDBName

End Sub


Public Sub MakeWorkTable(TableName As String, TemplateName As String)

' Create a table in the work database and a table linked to it in
the current database,
' modeled on a specified, existing table.

Dim dbCurr As DAO.Database
Dim tdf As DAO.TableDef
Dim lngError As Long

' Check whether the table to be created exists in the current
database, and if so
' whether it is a linked table.
Set dbCurr = DBEngine(0)(0)
dbCurr.TableDefs.Refresh
On Error Resume Next
Set tdf = dbCurr(TableName)
lngError = Err.Number
On Error GoTo 0

Select Case lngError
Case 0
' The table exists. If it's a linked table, we are willing
to delete it.
If Len(tdf.Connect) > 0 Then
dbCurr.TableDefs.Delete TableName
Else
Set tdf = Nothing
Set dbCurr = Nothing
Err.Raise 5, "Can't create work table '" & TableName & _
"' -- this table already exists in the
current database."
End If
Case 3265
' The table doesn't exist. That's what we hoped.
Case Else
' Some other error occurred, which is going to mess us up.
Set tdf = Nothing
Set dbCurr = Nothing
Err.Raise 5, "Can't create work table '" & TableName & _
"' -- error " & lngError & " accessing
table in the current database."
End Select
Set tdf = Nothing

' Create the temp table in the work database
DoCmd.TransferDatabase acExport, "Microsoft Access", mdbWorkDB.Name,
acTable, TemplateName, TableName, True
Application.Echo mblnEchoStatus ' Force Access to clear "Verifying
system objects ..." status bar message

mdbWorkDB.TableDefs.Refresh

' Create a linked table in this database, linked to the table in the
work database.
Set tdf = dbCurr.CreateTableDef(TableName)
tdf.Connect = ";DATABASE=" & mdbWorkDB.Name
tdf.SourceTableName = TableName
dbCurr.TableDefs.Append tdf
Set tdf = Nothing
dbCurr.TableDefs.Refresh

RefreshDatabaseWindow


MakeWorkTable_Exit:
Set dbCurr = Nothing
Exit Sub

End Sub
'----- end of module code -----
 
(PeteCresswell) said:
My superficial rationale is that inline SQL detracts from the
readability of the application. Instead of instantly comprehending
"qryFundMonthlyReturns_Create" and being able to see/modify the SQL
graphically, the maintenance programmer has to slog through the SQL.

There's something in what you say. I just can't think of a really good
way to make it work in this case.
But in reality, I think it's more a matter of habit than anything
else - and I'd change in a New York minute and never look back if I
thought it was necessary. For maintenance purposes, I could even
create new class of query: "zmqry..." for model queries that contain
the JCL used inline...

JCL? That takes me back to my IBM mainframe days, but I wonder if you
meant something else.
But I like the create-work-from-model-then-populate-it approach. I
don't even know why the few MakeTable queries that are in this app
are there - everything else uses the copy-model-then-append approach.
Also, now that I think about it, a slight weakness of MakeTable is
that you give up some control over the design of the table. It's
largely determined by the source recordset. Indexing and other stuff
can be pre-set in a model table instead of using a bunch of DAO code
to modify the results of a MakeTable.

That's the main reason I decided to do that with my clsWorkDB class --
it's so simple to manage, and I don't have to support a lot of complex
methods and properties.
Basically, I was just trolling for some innovative approach from this
great gathering of minds...

LOL Too bad the fishing wasn't very good.
 
I am *not* importunate! And I have two grown children to prove it!!

Fred

P.S. Or did you mean... impertinent?? ;)
P.P.S. Thanks!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top