Я хочу экспортировать содержимое нескольких таблиц из MSAccess2003. Таблицы содержат японские символы Unicode. Я хочу сохранить их как текстовые файлы с разделителями-тильдами.
Я могу сделать это вручную с помощью File / Export и в диалоговом окне «Advanced» выбрать тильду в качестве разделителя полей и Unicode в качестве кодовой страницы.
Я могу сохранить это как Спецификацию экспорта, но, похоже, это специфично для таблицы.
Я хочу экспортировать много таблиц с помощью кода VBA.
Пока я пробовал:
Sub ExportTables ()
Dim lTbl As Long
Dim dBase As Database
Dim TableName As String
Set dBase = CurrentDb
For lTbl = 0 To dBase.TableDefs.Count
'If the table name is a temporary or system table then ignore it
If Left(dBase.TableDefs(lTbl).Name, 1) = "~" Or _
Left(dBase.TableDefs(lTbl).Name, 4) = "MSYS" Then
'~ indicates a temporary table
'MSYS indicates a system level table
Else
TableName = dBase.TableDefs(lTbl).Name
DoCmd.TransferText acExportDelim, "UnicodeTilde", TableName, "c:\" + TableName + ".txt", True
End If
Next lTbl
Set dBase = Nothing
Конец подписки
Когда я запускаю это, я получаю исключение:
Ошибка времени выполнения '3011': Ядру базы данных Microsoft Jet не удалось найти объект «Allowance1 # txt». Убедитесь, что объект существует и вы правильно написали его имя и путь.
Если я отлаживаю на этом этапе, TableName будет «Allowance1», как и ожидалось.
Я предполагаю, что моя спецификация экспорта UnicodeTilde зависит от таблицы, поэтому я не могу использовать ее для нескольких таблиц.
Каково решение? Должен ли я использовать что-то еще, кроме TransferText, или, возможно, создать спецификацию экспорта программно?
Любая помощь приветствуется.





У меня есть часть ответа:
Я пишу файл schema.ini с помощью VBA, а затем делаю TransferText. Это создание формата экспорта на лету. Единственная проблема в том, что мой schema.ini содержит:
ColNameHeader = True
CharacterSet = Unicode
Format = Delimited(~)
Только строка заголовка выходит в юникоде с разделителями тильды. Остальные строки - ANSI с запятыми.
У меня для вас два предложения:
Убедитесь, что вы помещаете каждый параметр в файл [schema.ini] в новую строку. (Вы перечислили все это здесь в одной строке, поэтому я подумал, что обязательно позабочусь.)
Не забудьте указать аргумент CodePage (последний) при вызове TransferText. Вот список поддерживаемых значений, если он вам нужен:
http://msdn.microsoft.com/en-us/library/aa288104.aspx
В остальном, похоже, ваш подход должен работать.
В конце концов я решил это. (Сейчас я использую Access 2007, но у меня те же проблемы, что и с Access 2003.)
Во-первых, что не сработало:
TransferText сделает только строку заголовка разделенной в кодировке Unicode и тильдой, даже при правильно отформатированном файле schema.ini. (Нет, я не помещал все это в одну строку, это просто проблема форматирования HTML в stackoverflow.)
[MyTable.txt]
CharacterSet = Unicode
Format = Delimited(~)
ColNameHeader = True
NumberDigits = 10
Col1= "Col1" Char Width 10
Col2= "Col2" Integer
Col3= "Col3" Char Width 2
Просто используя оператор выбора:
SELECT * INTO [Text;DATABASE=c:\export\;FMT=Delimited(~)].[MyTable.txt] FROM [MyTable]
Полностью проигнорировал FMT. Мне было очень трудно найти документацию по формату параметров. Независимо от того, что я ввел в параметр FMT, единственное, что я мог заставить работать, было исправлено. Все остальное рассматривалось как CSVDelimited. Я мог бы проверить это, поскольку оператор select создал файл schema.ini следующим образом:
[MyTable.txt]
ColNameHeader=True
CharacterSet=1252
Format=CSVDelimited
Col1=Col1 Char Width 10
Col2=Col2 Integer
Col3=Col3 Char Width 2
В конечном итоге я решил создать свой файл schema.ini, а затем использовать оператор select. Код моего модуля выглядит примерно так:
Option Compare Database
Option Explicit
Public Function CreateSchemaFile(bIncFldNames As Boolean, _
sPath As String, _
sSectionName As String, _
sTblQryName As String) As Boolean
Dim Msg As String
On Local Error GoTo CreateSchemaFile_Err
Dim ws As Workspace, db As Database
Dim tblDef As TableDef, fldDef As Field
Dim i As Integer, Handle As Integer
Dim fldName As String, fldDataInfo As String
' -----------------------------------------------
' Set DAO objects.
' -----------------------------------------------
Set db = CurrentDb()
' -----------------------------------------------
' Open schema file for append.
' -----------------------------------------------
Handle = FreeFile
Open sPath & "schema.ini" For Output Access Write As #Handle
' -----------------------------------------------
' Write schema header.
' -----------------------------------------------
Print #Handle, "[" & sSectionName & "]"
Print #Handle, "CharacterSet = Unicode"
Print #Handle, "Format = Delimited(~)"
Print #Handle, "ColNameHeader = " & _
IIf(bIncFldNames, "True", "False")
Print #Handle, "NumberDigits = 10"
' -----------------------------------------------
' Get data concerning schema file.
' -----------------------------------------------
Set tblDef = db.TableDefs(sTblQryName)
With tblDef
For i = 0 To .Fields.Count - 1
Set fldDef = .Fields(i)
With fldDef
fldName = .Name
Select Case .Type
Case dbBoolean
fldDataInfo = "Bit"
Case dbByte
fldDataInfo = "Byte"
Case dbInteger
fldDataInfo = "Short"
Case dbLong
fldDataInfo = "Integer"
Case dbCurrency
fldDataInfo = "Currency"
Case dbSingle
fldDataInfo = "Single"
Case dbDouble
fldDataInfo = "Double"
Case dbDate
fldDataInfo = "Date"
Case dbText
fldDataInfo = "Char Width " & Format$(.Size)
Case dbLongBinary
fldDataInfo = "OLE"
Case dbMemo
fldDataInfo = "LongChar"
Case dbGUID
fldDataInfo = "Char Width 16"
End Select
Print #Handle, "Col" & Format$(i + 1) _
& "= """ & fldName & """" & Space$(1); "" _
& fldDataInfo
End With
Next i
End With
CreateSchemaFile = True
CreateSchemaFile_End:
Close Handle
Exit Function
CreateSchemaFile_Err:
Msg = "Error #: " & Format$(Err.Number) & vbCrLf
Msg = Msg & Err.Description
MsgBox Msg
Resume CreateSchemaFile_End
End Function
Public Function ExportATable(TableName As String)
Dim ThePath As String
Dim FileName As String
Dim TheQuery As String
Dim Exporter As QueryDef
ThePath = "c:\export\"
FileName = TableName + ".txt"
CreateSchemaFile True, ThePath, FileName, TableName
On Error GoTo IgnoreDeleteFileErrors
FileSystem.Kill ThePath + FileName
IgnoreDeleteFileErrors:
TheQuery = "SELECT * INTO [Text;DATABASE = " + ThePath + "].[" + FileName + "] FROM [" + TableName + "]"
Set Exporter = CurrentDb.CreateQueryDef("", TheQuery)
Exporter.Execute
End Function
Sub ExportTables()
Dim lTbl As Long
Dim dBase As Database
Dim TableName As String
Set dBase = CurrentDb
For lTbl = 0 To dBase.TableDefs.Count - 1
'If the table name is a temporary or system table then ignore it
If Left(dBase.TableDefs(lTbl).Name, 1) = "~" Or _
Left(dBase.TableDefs(lTbl).Name, 4) = "MSYS" Then
'~ indicates a temporary table
'MSYS indicates a system level table
Else
TableName = dBase.TableDefs(lTbl).Name
ExportATable (TableName)
End If
Next lTbl
Set dBase = Nothing
End Sub
Я не утверждаю, что это элегантно, но это работает. Также обратите внимание, что программе форматирования кода stackoverflow не нравится мой \ ", поэтому он не очень хорошо печатает мой код.
В отношении этого потока я наткнулся на невероятно простое решение, позволяющее использовать одну спецификацию для всех экспортов таблиц, тогда как обычно вам придется создавать отдельную спецификацию для каждой; или используйте подпрограмму, предоставленную Ричардом А.
Процесс выглядит следующим образом:
Создайте спецификацию, например Pipe |, разделенную любой таблицей, затем откройте запрос динамического набора в доступе с помощью SQL SELECT * FROM MSysIMEXColumns, а затем просто удалите все результирующие строки. Теперь эта спецификация не будет выдавать ошибку 3011, когда вы попытаетесь использовать таблицу, отличную от той, которую вы использовали для создания исходной спецификации, и по сути является универсальной спецификацией экспорта Pipe для любой таблицы / запроса, которую вы хотите.
Это было обнаружено / протестировано в Access 2003, поэтому я предполагаю, что будет работать и для более поздних версий.
С уважением,
Мэтт Доннан
Спасибо, Мэтт. Прошло много времени с тех пор, как я этим занимался, но я попробую, когда у меня будет минутка.