В 8 статье я показал, как перенести данные из текстового файла в создаваемый dbf файл. Я отметил, если текстовый файл очень большой, то очень затруднительно это сделать. Текстовый файл с разделителями может не помещаться на лист формата A4 и даже на формат A3. Тогда надо думать какие данные надо перенести и как еще это сделать. Если в редакторах FAR, и др. аналогичных можно еще увидеть упорядоченную разбивку данных как бы по полям, то в Блокноте и WordPad не всегда можно получить приличный вид текстового файла. Количество полей в dbf файлах на сегодня 254 по 254 символа (текст), а в некоторых приложения может быть и больше. При переносе из текстового файла надо это учитывать. Во фрагменте
'==============Ввод названий Полей базы данных для DBF
SQL="create table " & fileDBF & "("
for i=1 to 4 ' Если взять 15
stPol="st"&i
stDL= 19 ' Если взять 254
if i=4 then ' Если взять 15
SQL=SQL & "st" & i & " char(" & stDL & "))"
else
SQL=SQL & "st" & i & " char(" & stDL & "),"
end if
next
'==============Ввод названий Полей базы данных для DBF
Тут тоже можно сделать автоматический поиск и определить количество символов разделителей, если Вы уверены, что это тот разделить, или что Вам необходимо.
'========== Количество столбцов =======
Kstl=0
Str = Trim(TextStream.ReadLine())
for i=1 to Len(str)
if Mid(str,i,1)="|" Then
Kstl=Kstl+1
end if
next
if Kstl=0 then
WScript.Echo("Неправильно указан символ разделитель или нет такого символа")
WScript.Quit
end if
и отсюда
'==============Ввод названий Полей базы данных для DBF
SQL="create table " & fileDBF & "("
for i=1 to Kstl
stPol="st"&i
stDL= 19 ' Здесь можно подобрать длину поля (имя)
if i=Kstl then
SQL=SQL & "st" & i & " char(" & stDL & "))"
else
SQL=SQL & "st" & i & " char(" & stDL & "),"
end if
next
Но вот длину надо все-таки надо уточнять. Это не EXCEL и dbf формат. Да, можно проскочить файл и выбрать то же автоматически, но при этом все столбцы должны находиться на одном символьном расстоянии. Тогда это будет выглядеть так
'========== Количество символов в столбце =======
ReDim MassStrS(Kstl),MassRaz(Kstl)
k=0
Str = Trim(TextStream.ReadLine())
for i=1 to Len(str)
if Mid(str,i,1)="|" Then
k=k+1
MassStrS(k)=i
end if
next
for i=1 to Kstl
MassRaz(i)=(MassStrS(i)-MassStrS(i-1))-1
next
'========== Количество символов в столбце =======
Если же искать максимальную длину поля, то надо просмотреть весь текстовый файл.
Если же он небольшой, то можно сделать это быстро, а так надо довериться алгоритму.
'========== Максимальное количество символов в столбце =======
ReDim MassStrS(Kstl),MassMax(Kstl),MassRaz(Kstl)
nn=0
Do While Not TextStream.AtEndOfStream
k=0
nn=nn+1
Str = Trim(TextStream.ReadLine())
for i=1 to Len(str)
if Mid(str,i,1)="|" Then
k=k+1
MassStrS(k)=i
end if
next
for i=1 to k 'или Kstl
if nn=1 then
MassMax(i)=MassStrS(i)
else
if MassMax(i)<MassStrS(i) then
MassMax(i)=MassStrS(i)
end if
end if
Next
loop
SumSimv=0
for i=1 to Kstl
MassRaz(i)=(MassMax(i)-MassMax(i-1))-1
SumSimv=SumSimv+MassRaz(i)
Next
И это для того чтобы узнать значение SumSimv и оно должно быть меньше 3810, потому что переменная SQL может перенести только 3810 символов (254 символов на 15 полей-заголовок).
if SumSimv>3810 then
WScript.Echo("Общее количество символов больше 3810")
WScript.Quit
end if
'========== Максимальное количество символов в столбце =======
И опять меняем
'==============Ввод названий Полей базы данных для DBF
SQL="create table " & fileDBF & "("
for i=1 to Kstl
stPol="st"&i
stDL= MassRaz(i) ' Здесь есть длина поля (имя)
if i=Kstl then
SQL=SQL & "st" & i & " char(" & stDL & "))"
else
SQL=SQL & "st" & i & " char(" & stDL & "),"
end if
next
'==============Ввод названий Полей базы данных для DBF
И опять и снова
Set TextStream = FileName.OpenAsTextStream(1)
А можно и вот так
ReDim MassStrS(Kstl),MassMax(Kstl)
iss=1
nn=0
While Not TextStream.AtEndOfStream
Str = TextStream.ReadLine()
nn=nn+1
for j=1 to Kstl
InSimv=InStr(iss,Str,"|",1) ' Ставим символ разделитель строки
st=Trim(Mid(Str,iss,InSimv-iss))
MassStrS(j)=len(st)
if MassStrS(j)=0 then
MassStrS(j)=9 ' Если поле пустое т.е. имеет текст состоящий из одних пробелов
end if
if nn=1 then
MassMax(j)=MassStrS(j)
else
if MassMax(j)<MassStrS(j) then
MassMax(j)=MassStrS(j)
end if
end if
iss=InSimv+1
next
iss=1
Wend
nn=0
Erase MassStrS
SumSimv=0
for i=1 to Kstl
SumSimv=SumSimv+MassMax(i)
next
Это уже с нормализацией, но можно сделать из dbf файла. В общем можно придумать множество решений и алгоритмов определения необходимой длины столбца (количество символов строки в колонке, если правильно указан символ разделитель). Можно создать массив полей и автоматически записать в dbf файл. В текстовый файл можно скидывать по строке до 2 гб. символов. Сам я не проверял, но в редакторе FAR просматривал большие файлы и строки в них были больше указанного количества символов 3810. В ИНТЕРНЕТе Я видел это решение. В основном решается как рекурсия. Из этого значит, что большие по своему объему dbf файлы могут перевести все данные в текстовый файл, и они уместятся, но опять же не превышая 2 гб. А вот перевести из текстового файла в dbf автоматически иногда проблематично из определенных ограничений. Да можно перенести выделенные данные, но их надо еще подготовить к этому. Если файл небольшой то его можно как то к этому приспособить, а если большой, то уж как получиться. Конечно, можно попросить Айти специалиста или Программиста за это взяться. И этим довести их до паники и бегства. А потом, если у этих специалистов нет на это решения, то они могут вообще отстраниться от этого. И начальство заставит Вас думать, как это сделать, а им будет СЛАВА. Тогда встал вопрос, а зачем переносить данные из dbf в текстовый файл. Сумасшествие рядом и как отпустить такую ситуацию, перескочившей горизонт событий от нечего делать. Давайте подумаем так. Вам необходимо посмотреть, что находится в dbf файле, и специальных штатных приложений нет. Просматривать dbf с помощью Блокнота и в других, не приспособленных для этого редакторах тяжко, и если Вы вообще не разбираетесь в структуре dbf, то запутаетесь, и может пропасть желание в дальнейшем узнавании. Все редакторы, которые входят в состав OC, не приспособлены, оказать Вам помощь в этом. Также можете отредактировать некоторые данные и даже если их немного вернуть опять в dbf с определенными параметрами (тип, длина и т.д.). Вот здесь можно немного поработать и также освоиться, если Вам это необходимо. Причем Вы можете понять, какие поля необходимы, а какие нет. В текстовый файл можно сохранить с помощью WDBFVIEW и др., но если они у Вас есть. Здесь вы не подведете шапку с заголовками, и если в строке будут переводы строк, то в некоторых случаях Вы получите кашу символов, которую Вам придется так сказать разгребать, а проще исправлять и приводить к читабельному порядку. Конечно, ко всему возможно приспособиться, но это время и хорошо, если Вы властелин времени или Ваши сотрудники это знают. Здесь есть непреодолимое желание смотреть на все проще, но не всегда так выходит. Из всего этого есть понятие, что все взаимозаменяемо и ничего нового. Если можно создать dbf или EXCEL файл и др. то перевести их в текстовый файл или обратно или друг в друга, не сложно, если знать инструменты перевода. А это и приложения и программы и немного понятия, что это такое и для чего Вам это нужно или необходимо. Теперь рассмотрим и разберем скрипт, с помощью которого выводим данные из dbf файла в текстовый файл. В основном под текстовым файлом будем просто подразумевать файл TXT.
'*******************************************************************
' Имя: AdoED9Z.vbs
' Язык: VBScript
' Описание: Вывод данных из DBF файла в TXT
' Автоматическое создание шапки (в заголовках свои имена полей)
' Замена в строке символа ПЕРЕВОДА СТРОКИ на пробел
' ODBC и ADO только для dBase
'*******************************************************************
Set WshShell=WScript.CreateObject("WScript.Shell")
SDefaultDir=WshShell.CurrentDirectory
Set FSO = CreateObject("Scripting.FileSystemObject")
FileTekst=SDefaultDir & "\_TEKST.txt" 'Текстовый файл вывода
'=========== Проверка файла
Set FSO = CreateObject("Scripting.FileSystemObject")
If FSO.FileExists(FileTekst) Then
'MsgBox "Файл есть! Удаляем"
FSO.DeleteFile FileTekst
End if
'========== Проверка файла
NameFilDBF=SDefaultDir & "\_222.dbf"
'========== Проверка файла
If FSO.FileExists(NameFilDBF) Then
else
MsgBox "Нет файла "&NameFilDBF
WScript.Quit
end if
'========== Проверка файла
'======== Если данные в файле с не русской кодировкой устанавливаем 866 Если с русской можете заремачить =======
Set oFile = FSO.GetFile(NameFilDBF)
With oFile.OpenAsTextStream()
readBinary = .Read(oFile.Size)
.Close
End With
readBinary=left(readBinary,29)+"e"+mid(readBinary,31)
With FSO.createTextFile(NameFilDBF)
.Write(readBinary)
.Close
End With
'======== Если данные в файле с не русской кодировкой устанавливаем 866 =======
FileTekst=SDefaultDir & "\_TEKST.txt" 'Файл вывода
'=========== Проверка файла
Set FSO = CreateObject("Scripting.FileSystemObject")
If FSO.FileExists(FileTekst) Then
'MsgBox "Файл есть! Удаляем"
FSO.DeleteFile FileTekst
End if
'========== Проверка файла
'=================== dBase ==================
Set RSN=WScript.CreateObject("ADODB.Recordset")
Set conn = CreateObject("ADODB.Connection")
conn.CursorLocation = 3
conn.Open "Driver={Microsoft dBase Driver (*.dbf)};DBQ=" & SDefaultDir & ";"
strSQLdbf="SELECT * FROM " & NameFilDBF & " "
Set RS = conn.Execute(strSQLdbf)
objKlRecs=RS.RecordCount 'Количество строк в DBF файле
objKlFields = RS.Fields.count 'Количество колонок в DBF файле
'=================== dBase ==================
'=================== Максимальное значение поля в DBF ==========
ReDim MassDL(objKlFields-1)
for i=0 to objKlFields-1
st=RS.Fields(i).Name
strSQLnn="SELECT Max(Len(" & st & ")) FROM " & NameFilDBF & " "
set RSQQ = conn.Execute(strSQLnn)
v=RSQQ.Fields (0).Value
if IsEmpty(v) then
v=9
end if
if IsNull(v) then
v=9
end if
if v="" then
v=254
end if
if v=0 then
v=9
end if
MassDL(i)=v
v=""
next
v=0
RSQQ.Close
Set RSQQ = Nothing
'=================== Максимальное значение поля в DBF ==========
Const ForWriting = 2 ' На запись
Set FOut = FSO.OpenTextFile(FileTekst,ForWriting,true)
' ==============Ввод названий Полей базы данных
FOut.WriteLine NameFilDBF 'Вывод имен полей DBF
FOut.WriteLine "==================================================================================="
FOut.WriteLine "№ |Наименование поля|Тип поля | Длина поля (байт)"
FOut.WriteLine "==================================================================================="
StrP="" 'Можете это и не ставить
TypeP=""
RazmP=""
UmolP=""
ZnacP=""
McifP=""
Nnom=0
for i=0 to objKlFields-1
Nnom=Nnom+1
StrP=RS.Fields(i).Name
TypeP=RS.Fields(i).Type
RazmP=RS.Fields(i).ActualSize
UmolP=RS.Fields(i).DefinedSize
ZnacP=RS.Fields(i).NumericScale
McifP=RS.Fields(i).Precision
Nnom=Space(3-Len(Nnom))&Nnom
if len(StrP)<>17 then
StrP=StrP+Space(17-Len(StrP))
else
StrP=Left(StrP,17)
end if
if TypeP=200 then
Tpolzn="Строковое значение"
else
if TypeP=5 then
Tpolzn="Целое с плавающей запятой двойной точности"
else
if TypeP=133 then
Tpolzn="Дата"
else
Tpolzn="Тип неопределен" 'Возможен другой тип
end if
end if
end if
if len(Tpolzn)<>42 then
Tpolzn=Tpolzn+Space(42-Len(Tpolzn))
else
Tpolzn=Left(Tpolzn,42)
end if
if len(UmolP)<>18 then
UmolP=Space(18-len(UmolP))&UmolP
else
UmolP=Left(UmolP,18)
end if
FOut.WriteLine Nnom & " " & StrP & " " & Tpolzn & " " & UmolP
next
FOut.WriteLine "==================================================================================="
FOut.WriteLine
strStb=""
StrP=""
ReDim DlStrS(objKlFields-1)
for i=0 to objKlFields-1
stDL=MassDL(i)
StrP=RS.Fields(i).Name
if stDl<Len(StrP) then
stDL=Len(StrP)
end if
if i=objKlFields-1 then
'strStb=strStb & StrP & Space(stDL-Len(StrP)) ' Оставил если не нужна завершающая литера в конце заголовка
strStb=strStb & StrP & Space(stDL-Len(StrP)) & "|"
else
strStb=strStb & StrP & Space(stDL-Len(StrP)) & "|" ' Можете поставить свой символ разделить по колонкам
end if
DlStrS(i)=len(StrP+Space(stDL-Len(StrP)))
next
FOut.WriteLine String(len(strStb),"=")
FOut.WriteLine strStb
FOut.WriteLine String(len(strStb),"=")
' ============== Ввод данных из DBF файла
for i=1 to objKlRecs
vvv=""
for j=0 to objKlFields-1
stShap=DlStrS(j)
st=Trim(RS.Fields(j))
if IsNull(st) then
st=" "
else
st=UprSimv(st) 'Функция замена символа ПЕРЕВОДА СТРОКИ в строке символов
end if
if j=objKlFields-1 then
'vvv=vvv & st & "" 'Оставил, если не понадобится последняя колонка
vvv=vvv & st & "" & space(stShap-len(st)) & "|"
else
vvv=vvv & st & "" & space(stShap-len(st)) & "|"
end if
next
FOut.WriteLine vvv
' FOut.WriteBlankLines 2 ' записать в файл указанное количество пустых строк
RS.MoveNext
next
'-----------------------
Function UprSimv(s) 'Поиск символа перевода строки и замена его на пробел
ss=""
' Здесь можно явно указать переменную с помощью DIM i и убрать ii
For ii=1 To Len(s) ' Проверяем все символы в строке.
k = Asc(Mid(s,ii,1)) ' Рассматриваем и определяем ANSI-код каждого символа. Шаг 1 символ в строке
ks=Mid(s,ii,1)
'Кроме перевода строки может попасться и что то другое
if k=10 then 'Находим символ перевода строки
ss= left(ss,LEN(ss)-1)
ks=chr(32)
ss=ss+ks
else
ss=ss+ks
end if
Next
UprSimv=ss
End Function
'-----------------------
Erase MassDL
Erase DlStrS
FOut.WriteLine String(len(strStb),"=")
Set WshShell=Nothing
Set FSO = Nothing
Set oFile=Nothing
FOut.Close
Set FOut=Nothing
conn.close
Set conn = Nothing
Set RS = Nothing
Set RSN = Nothing
WScript.Echo("Файл создан!")
WScript.Quit
Да, текст получился большой, но можно и переделать.
А вот так выглядит итоговое решение
Эти данные перенесены из файла _222.dbf. Смотрятся данные этого файла так:
Вытащить текстовую информацию из рисунка можно современными действиями Гугл и Яндекс если файл небольшой и количество полей и данных не так много, но а так только переводом информации. Есть еще вариант как сделать еще легче, но здесь я не показал шапку с заголовками.
v=RS.GetString 'Вывод в текст'
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set tsOut = objFSO.CreateTextFile("FileTxt.txt", True, False) 'создаём файл в ASCII, при наличии файл перезаписывается
tsOut.WriteLine v
Set WshShell=Nothing
Set FSO = Nothing
Set RS = Nothing
Set objFSO=Nothing
tsOut.Close
Set tsOut=Nothing
conn.close
Set conn=Nothing
WScript.Echo("Файл создан!")
Выбирать каждому свое.
В скрипт AdoED9Z.vbs можно добавить вот такой фрагмент и создаем файл AdoED9U.vbs
Set objArgs=WScript.Arguments
if objArgs.Count>0 then
fileVvod=objArgs(0)
else
WScript.Echo "Введите имя файла DBF после AdoED9U.vbs"
WScript.Quit
end if
' ==== Ввод файла dbf через строку данные которого надо перевести в создаваемый во время процесса текстовый файл ====
NameFilDBF = FSO.GetFile(fileVvod)
'========== Проверка файла
sStr=len(trim(NameFilDBF))
if uCase(Mid(trim(NameFilDBF),sStr-3,4))<>".DBF" then
MsgBox "Это не файл DBF"
WScript.Quit
end if
'========== Проверка файла
Файлы в архиве Файлы9.rar. В архив я еще включил 2 файла скрипта с разным алгоритмом построения решения. Это файлы которые переводят данные из текстового файла в dbf. Они по действию подходят к файлам для статьи 8. Это файлы AdoED8Z.vbs и AdoED8U.vbs Файлы можно редактировать, а также переделать на JScript. Попробуйте Сами отработать большой dbf файл. И если Вам это тема интересна можете написать свои впечатления и свои достижения внизу под этой статьей.
Ссылка на файл https://disk.yandex.ru/d/Hj_znyk1Y5zCjA
Подписывайтесь на мой канал и ставьте лайки.