2009-10-20 124 views
6

Así que me gustaría copiar una tabla vinculada a una local en código, estructura y datos en MS Access 2003.¿Cómo copiar una tabla vinculada a una tabla local en Ms Access programmatically?

El código es: VBA o C#. O cualquier otra cosa para el caso.

ACTUALIZACIÓN: deseo que la estructura de copia y el comportamiento de los datos del acceso ms mantengan las claves primarias. Si copia una tabla vinculada, puede optar por pegarla como 'estructura y datos (tabla local)' Es lo que quiero lograr en el código.

Respuesta

6

Según tengo entendido, DAO no es compatible con el tipo de datos decimal, pero ADOX sí. Aquí hay un procedimiento actualizado que usa ADOX para copiar el esquema a una nueva tabla.

Un elemento interesante de la nota: El proveedor OLEDB para Jet ordena las columnas alfabéticamente en lugar de por posición ordinal como se explica in this KB article. No me preocupaba preservar la posición ordinal, pero puede que sí, en cuyo caso puede actualizar este procedimiento para satisfacer sus necesidades.

Para que la versión ADOX del código funcione, deberá establecer una referencia a Microsoft ADO Ext. 2.x para DDL y seguridad (donde x = número de versión; utilicé 2.8 para probar este procedimiento). También necesitarás una referencia a ADO también.

Public Sub CopySchemaAndData_ADOX(ByVal sourceTableName As String, ByVal destinationTableName As String) 
On Error GoTo Err_Handler 

Dim cn As ADODB.Connection 
Dim cat As ADOX.Catalog 
Dim sourceTable As ADOX.Table 
Dim destinationTable As ADOX.Table 

Set cn = CurrentProject.Connection 
Set cat = New ADOX.Catalog 
Set cat.ActiveConnection = cn 

Set destinationTable = New ADOX.Table 
destinationTable.Name = destinationTableName 

Set sourceTable = cat.Tables(sourceTableName) 

Dim col As ADOX.Column 
For Each col In sourceTable.Columns 
    Dim newCol As ADOX.Column 
    Set newCol = New ADOX.Column 

    With newCol 
     .Name = col.Name 
     .Attributes = col.Attributes 
     .DefinedSize = col.DefinedSize 
     .NumericScale = col.NumericScale 
     .Precision = col.Precision 
     .Type = col.Type 
    End With 

    destinationTable.Columns.Append newCol 
Next col 

Dim key As ADOX.key 
Dim newKey As ADOX.key 

Dim KeyCol As ADOX.Column 
Dim newKeyCol As ADOX.Column 
For Each key In sourceTable.Keys 
    Set newKey = New ADOX.key 
    newKey.Name = key.Name 
    For Each KeyCol In key.Columns 
     Set newKeyCol = destinationTable.Columns(KeyCol.Name) 
     newKey.Columns.Append (newKeyCol) 
    Next KeyCol 

    destinationTable.Keys.Append newKey 
Next key 

cat.Tables.Append destinationTable 

'Finally, copy data from source to destination table 
Dim sql As String 
sql = "INSERT INTO " & destinationTableName & " SELECT * FROM " & sourceTableName 
CurrentDb.Execute sql 

Err_Handler: 
    Set cat = Nothing 
    Set key = Nothing 
    Set col = Nothing 
    Set sourceTable = Nothing 
    Set destinationTable = Nothing 
    Set cn = Nothing 

    If Err.Number <> 0 Then 
     MsgBox Err.Number & ": " & Err.Description, vbCritical, Err.Source 
    End If 
End Sub 

Este es el procedimiento original de DAO

Public Sub CopySchemaAndData_DAO(SourceTable As String, DestinationTable As String) 
On Error GoTo Err_Handler 

Dim tblSource As DAO.TableDef 
Dim fld As DAO.Field 

Dim db As DAO.Database 
Set db = CurrentDb 

Set tblSource = db.TableDefs(SourceTable) 

Dim tblDest As DAO.TableDef 
Set tblDest = db.CreateTableDef(DestinationTable) 

'Iterate over source table fields and add to new table 
For Each fld In tblSource.Fields 
    Dim destField As DAO.Field 
    Set destField = tblDest.CreateField(fld.Name, fld.Type, fld.Size) 
    If fld.Type = 10 Then 
     'text, allow zero length 
     destField.AllowZeroLength = True 
    End If 
    tblDest.Fields.Append destField 
Next fld 

'Handle Indexes 
Dim idx As Index 
Dim iIndex As Integer 
For iIndex = 0 To tblSource.Indexes.Count - 1 
    Set idx = tblSource.Indexes(iIndex) 
    Dim newIndex As Index 
    Set newIndex = tblDest.CreateIndex(idx.Name) 
    With newIndex 
     .Unique = idx.Unique 
     .Primary = idx.Primary 
     'Some Indexes are made up of more than one field 
     Dim iIdxFldCount As Integer 
     For iIdxFldCount = 0 To idx.Fields.Count - 1 
     .Fields.Append .CreateField(idx.Fields(iIdxFldCount).Name) 
     Next iIdxFldCount 
    End With 

    tblDest.Indexes.Append newIndex 
Next iIndex 

db.TableDefs.Append tblDest 

'Finally, copy data from source to destination table 
Dim sql As String 
sql = "INSERT INTO " & DestinationTable & " SELECT * FROM " & SourceTable 
db.Execute sql 

Err_Handler: 
    Set fld = Nothing 
    Set destField = Nothing 
    Set tblDest = Nothing 
    Set tblSource = Nothing 
    Set db = Nothing 

    If Err.Number <> 0 Then 
     MsgBox Err.Number & ": " & Err.Description, vbCritical, Err.Source 
    End If 
End Sub 
+0

Tx hombre! Dime, ¿sabes por qué algo tan obvio como esto (mantener las claves primarias) no es compatible con los datos de importación en el acceso? – Peter

+0

No tengo idea, especialmente teniendo en cuenta cuánto tiempo ha estado cerca el acceso. Creerías que sería una opción al menos ... –

+0

No funciona para decimales Tengo miedo ... – Peter

0

tratar docmd.CopyObject o docmd.TransferDatabase

+1

¿No se acaba de copiar la tabla vinculada en lugar de hacer una tabla local? – Peter

+0

sí, en mi experiencia, ejecutando Docmd.CopyObject "dest_table", acTable, "source_table" donde la tabla de origen es una tabla vinculada, solo crea una copia del enlace a la misma tabla ... – avguchenko

-1

Crear esta consulta y ejecutarlo

SELECT * INTO MyNewTable FROM LinkedTableName

En VBA se puede hacer

docmd.runsql "SELECT * INTO MyNewTable FROM LinkedTableName"

Para mantener la estructura que tendría que hacer DoCmd.TransferDatabase acImport

+1

See update please, this consulta no guardará las claves principales – Peter

+0

No, la importación también pierde las claves al parecer – Peter

Cuestiones relacionadas