Поиск по сайту:


«VBA Использование файлов в VBA»

Файл: 4 КБ
Поделиться:
Начиная с первых версий VBA, файлы обрабатывались с помощью оператора Open и других файловых операторов и функций. Эти механизмы со временем будут вытеснены объектной моделью FSO (File System Object), но они полностью поддерживаются в версии 5.0.
Типы доступа к файлам. Сам по себе файл не представляет ничего более, чем ряд связанных байтов, расположенных на диске. Когда приложение обращается к файлу, оно должно знать, что содержат эти байты (символы, целые числа, строки и т.д.) Тип данных, содержащихся в файле, определяет тип доступа к файлу. VBA три типа доступа к файлу:
Последовательный доступ, обычно используемый для записи текстовых файлов, например протоколов ошибок или отчетов.
Произвольный доступ, используемый при необходимости считать и записать данные в файл без его закрытия. Файлы произвольного доступа содержат данные в виде записей, которые упрощают и ускоряют поиск нужных сведений.
Двоичный доступ, используется, когда требуется считать или записать байт в любую позицию в файле, например при сохранении или отображении точечных изображений.
Последовательный доступ предполагает, что каждый символ в файле либо является текстовым символом, либо входит в форматирующую последовательность текста, как, например, символ новой строки. Данные хранятся, как символы в коде ANSI. Предполагается, что файл, открытый для произвольного доступа, составлен из множества записей одинаковой длины. Можно применять определенные пользователем типы для создания записей, составленных из нескольких полей, каждое из которых может иметь разный тип данных. Данные хранятся как двоичная информация.
Двоичный доступ позволяет использовать файлы для хранения любых данных. Такой доступ похож на произвольный, за исключением того, что не существует никаких предположений о типе данных или длине записи. Однако необходимо точно знать, как данные были записаны в файл, чтобы можно было корректно извлекать их.
Функции и операторы доступа к файлам. Ряд функций и операторов может быть применен для файлов всех трех типов, а некоторые работают только с файлами одного или двух типов. Со всеми типами доступа к файлам используют следующие :
Для работы с папками и дисками:
Функция Dir возвращает значение типа String, представляющее имя файла, каталога или папки, которое удовлетворяет указанному шаблону имени файла, набору атрибутов файла или метке тома на диске.
Dir[(путь[, атрибуты])]
Здесь путь (Необязательный) - строковое выражение, указывающее имя файла; может содержать имя каталога или папки и диска. Если путь не найден, возвращается пустая строка (""). Атрибуты (Необязательный) - константа или числовое выражение, описывающее атрибуты файла. Если этот аргумент опущен, возвращаются все файлы, имена которых удовлетворяют аргументу путь.
Функция Dir поддерживает использование подстановочных знаков для нескольких символов (*) и для одиночного символа (?) для указания нескольких файлов.
При первом вызове функции Dir необходимо указать путь, в противном случае возникает ошибка. Если указаны атрибуты файла, наличие аргумента путь является обязательным.
Функция Dir возвращает первое имя файла, имя которого удовлетворяет аргументу путь. Для получения остальных файлов, имена которых удовлетворяют указанному пути, следует повторно вызвать функцию Dir без аргументов. Если файлов, имена которых удовлетворяют указанному пути, не осталось, возвращается пустая строка (""). При следующем после возврата пустой строки вызове функции необходимо указать аргумент путь; в противном случае возникает ошибка. Изменить значение аргумента путь можно в любой момент, не дожидаясь, пока закончатся файлы, имена которых удовлетворяют текущему пути. Рекурсивный вызов функции Dir запрещен. Вызов функции Dir с атрибутом vbDirectory не приводит к последовательному возврату подкаталогов.
Поскольку имена файлов возвращаются в произвольном порядке, их можно сохранить в массиве, а затем отсортировать этот массив.
Пример: ' Возвращает список каталогов на диске C:.
MyPath = "c:\"	' Указывает путь.
MyName = Dir(MyPath, vbDirectory)	' Возвращает первый элемент.
Do While MyName <> ""	' Начинает цикл.
' Игнорирует текущий каталог и каталог предыдущего уровня.
If MyName <> "." And MyName <> ".." Then
' является ли MyName каталогом.
If (GetAttr(MyPath & MyName) And vbDirectory) = vbDirectory Then
Debug.Print MyName	' Выводит элемент если это каталог
End If	.
End If
MyName = Dir	' Возвращает следующий элемент.
Loop
Инструкция ChDir - Изменяет текущий каталог или папку.
ChDir путь
Обязательный аргумент путь является строковым выражением, определяющим какой каталог (или папка) станет текущим. Аргумент путь может содержать имя диска. Если диск не указан, инструкция ChDir изменяет текущий каталог или папку на текущем диске.
Инструкция ChDir изменяет текущий каталог, но не изменяет стандартный диск. Например, если стандартным является диск C, то после выполнения следующей инструкции стандартным каталогом станет каталог на диске D, но стандартным диском останется диск C:
ChDir "D:\TMP"
Функция CurDir - Возвращает значение типа Variant (String), представляющее текущий путь.
CurDir[(диск)]
Необязательный аргумент диск является строковым выражением, указывающим существующий диск. Если диск не указан или аргумент диск является пустой строкой (""), функция CurDir возвращает путь к текущему диску.
Инструкция MkDir - Создает новый каталог или папку.
MkDir путь
Обязательный аргумент путь является строковым выражением, определяющим создаваемый каталог или папку. Аргумент путь может содержать имя диска. Если диск не указан, инструкция MkDir создает новый каталог или папку на текущем диске.
Инструкция RmDir - Удаляет существующий каталог или папку.
RmDir путь
Обязательный аргумент путь является строковым выражением, определяющим каталог или папку, которую следует удалить. Аргумент путь может содержать имя диска. Если диск не указан, инструкция RmDir удаляет каталог или папку с текущего диска.
При попытке удалить с помощью инструкции RmDir каталог (или папку), который содержит файлы, возникает ошибка. Для предварительного удаления всех файлов из каталога или папки следует использовать инструкцию Kill.
Инструкция ChDrive - Изменяет текущий диск.
ChDrive диск
Обязательный аргумент диск является строковым выражением, указывающим существующий диск. Если этот аргумент задается пустой строкой (""), текущий диск не изменится. Если диск является строкой, состоящей из нескольких символов, инструкция ChDrive использует только первый символ.
Для работы со свойствами файлов:
Функция FileDateTime - Возвращает значение типа Variant (Date), содержащее дату и время создания или последнего изменения файла.
FileDateTime(путь)
Обязательный аргумент путь является строковым выражением, указывающим имя файла. Аргумент путь может содержать имя каталога или папки и диска.
Функция FileLen - Возвращает значение типа Long, содержащее размер файла в байтах.
FileLen(путь)
Обязательный аргумент путь является строковым выражением, определяющим файл. Аргумент путь может содержать имя каталога или папки и диска.
Если в момент вызова функции FileLen указанный файл открыт, возвращается размер этого файла до его открытия. Для определения размера открытого файла следует использовать функцию LOF.
Функция GetAttr - возвращает значение типа Integer, содержащее атрибуты файла, каталога или папки.
GetAttr(путь)
Обязательный аргумент путь является строковым выражением, указывающим имя файла. Аргумент путь может содержать имя каталога или папки и диска.
Значение, возвращаемое функцией GetAttr, являются суммой следующих значений:
vbNormal 0 Обычный.
vbReadOnly 1 Только чтение.
vbHidden 2 Скрытый.
vbSystem 4 Системный.
vbDirectory 16 Каталог или папка.
vbArchive 32 Файл был изменен после последнего резервирования.
Для определения установленных атрибутов следует с помощью оператора And выполнить поразрядное сравнение значения, возвращенного функцией GetAttr , и значения, соответствующего нужному атрибуту файла. Ненулевой результат означает, что данный атрибут установлен. Например, значение следующего выражения будет нулевым, если архивный атрибут не установлен:
Result = GetAttr(FName) And vbArchive
Если архивный атрибут установлен, будет возвращено ненулевое значение.
Инструкция SetAttr - задает атрибуты файла.
SetAttr pathname, attributes
Здесь pathname (Обязательный) - строковое выражение, указывающее имя файла; может содержать имя каталога или папки и диска.
attributes (Обязательный) - константа или числовое выражение, задающее атрибуты файла.
Ниже приведены допустимые значения аргумента attributes:
vbNormal 0 Обычный (по умолчанию).
vbReadOnly 1 Только чтение.
vbHidden 2 Скрытый.
VbSystem 4 Системный.
vbArchive 32 Файл был изменен после последнего резервирования.
При попытке изменения атрибутов открытого файла возникает ошибка выполнения.
Для манипулирования файлами:
Инструкция FileCopy - Копирует файл.
FileCopy source, destination
Здесь source (Обязательный) - строковое выражение, указывающее имя файла, подлежащего копированию. Аргумент source может содержать имя каталога или папки и диска.
destination (Обязательный) - строковое выражение, указывающее имя результирующего файла. Аргумент destination может содержать имя каталога или папки и диска.
При попытке скопировать открытый файл с помощью инструкции FileCopy возникает ошибка.
Инструкция Name - Изменяет имя файла, каталога или папки.
Name староеИмя As новоеИмя
Здесь староеИмя (Обязательный) - строковое выражение, указывающее имя и положение существующего файла; может содержать имя каталога или папки и диска.
новоеИмя (Обязательный) - строковое выражение, указывающее новое имя и положение файла; может содержать имя каталога или папки и диска. Файл с таким именем не должен существовать.
Оба аргумента, новоеИмя и староеИмя, должны указывать на один и тот же диск. Если путь, указанный с помощью аргумента новоеИмя существует и отличен от указанного с помощью аргумента староеИмя, инструкция Name переместит файл в новый каталог или папку и переименует его (если требуется). Если пути, указанные с помощью аргументов новоеИмя и староеИмя, разные, а имена файлов совпадают, инструкция Name переместит файл в новый каталог или папку без изменения его имени. С помощью инструкции Name, можно переместить файл из одного каталога (или папки) в другой, однако нельзя переместить каталог или папку.
При попытке переименовать открытый файл с помощью инструкции Name возникает ошибка. Прежде чем приступить к изменению имени файла, необходимо его закрыть. В аргументах инструкции Name не допускается использование подстановочных знаков для нескольких символов (*) и оного символа (?).
Инструкция Kill - удаляет файлы с диска.
Kill путь
Обязательный аргумент путь является строковым выражением, указывающим имена одного или нескольких файлов, подлежащих удалению. Аргумент путь может содержать имя каталога или папки и диска.
Инструкция Kill поддерживает использование подстановочных знаков для нескольких символов (*) и для одиночного символа (?) для указания нескольких файлов.
При попытке удалить открытый файл с помощью инструкции Kill возникает ошибка. Для удаления каталогов следует использовать инструкцию RmDir.
Для управления файлами:
Инструкция Open - разрешает выполнение с файлом операций ввода/вывода.
Open путь For режим [Access доступ] [блокировка] As [#]номерФайла [Len=длина]
Здесь путь (Обязательный) - строковое выражение, указывающее имя файла; может содержать имя каталога или папки и имя диска.
режим (Обязательный) - ключевое слово, указывающее режим файла: Append, Binary, Input, Output или Random. По умолчанию, файл открывается в режиме Random.
доступ (Необязательный) - ключевое слово, указывающее операции, разрешенные с открытым файлом: Read, Write или Read Write.
блокировка (Необязательный) - ключевое слово, указывающее операции, разрешенные с открытым файлом другим процессам: Shared, Lock Read, Lock Write и Lock Read Write.
номерФайла (Обязательный) - допустимый номер файла в интервале от 1 до 511 включительно. Для определения следующего свободного номера файла следует использовать функцию FreeFile.
длина (Необязательный) - Число, меньшее либо равное 32 767 (байт). Для файлов, открытых в режиме Random, это значение является длиной записи. Для файлов с последовательным доступом это значение является числом буферизуемых символов.
Чтобы получить возможность выполнить любую операцию ввода/вывода, файл необходимо открыть. Инструкция Open резервирует буфер ввода/вывода для файла и определяет режим использования этого буфера.
Если аргумент путь описывает несуществующий файл, такой файл будет создан при открытии в режиме Append, Binary, Output или Random.
Если файл уже открыт другим процессом и указанный режим доступа не разрешен, инструкция Open не будет выполнена и возникнет ошибка.
Если аргумент режим имеет значение Binary, предложение Len игнорируется.
В режимах Binary, Input и Random можно еще раз открыть уже открытый файл под другим номером, не закрывая его. В режиме Append и Output необходимо закрыть файл, чтобы получить возможность открыть его еще раз под другим номером.
Функция FreeFile - Возвращает значение типа Integer, представляющее следующий номер файла, доступный для использования с инструкцией Open.
FreeFile[(диапазонНомеров)]
Необязательный аргумент диапазонНомеров является выражением типа Variant, указывающим диапазон, из которого возвращается следующий свободный номер файла. Значение 0 (используется по умолчанию) задает возвращение номера файла из диапазона 1 - 255 включительно. Значение 1 задает возвращение номера файла из диапазона 256 - 511.
Функцию FreeFile используют для возвращения незанятого номера файла.
Инструкция Close - завершает операции ввода/вывода с файлом, открытым с помощью инструкции Open.
Close [списокНомеровФайлов]
Необязательный аргумент списокНомеровФайлов может представлять один или несколько номеров файлов. При этом используется следующий синтаксис, где номерФайла представляет любой допустимый номер файла:
[[#]номерФайла] [, [#]номерФайла] . . .
Если аргумент списокНомеровФайлов опущен, закрываются все активные файлы, открытые с помощью инструкции Open.
При закрытии файла, открытого в режиме Output или Append, в него добавляется содержимое последнего буфера вывода. Все буферы, связанные с закрытым файлом, освобождаются.
Инструкция Close разрывает связь между файлом и соответствовавшим ему номером файла.
Инструкция Reset - Закрывает все файлы, открытые с помощью инструкции Open.
Reset
Инструкция Reset закрывает все активные файлы, открытые с помощью инструкции Open, и записывает содержимое всех буферов файлов на диск.
Для позиционирования в открытом файле:
Функция Seek - возвращает значение типа Long, определяющее текущее положение указателя чтения/записи внутри файла, открытого с помощью инструкции Open.
Seek(номерФайла)
Обязательный аргумент номерФайла является выражением типа Integer, содержащим допустимый номер файла.
Функция Seek возвращает значение в интервале от 1 до 2 147 483 647 (т.е. 2^31 - 1) включительно.
Ниже приведено описание значений, возвращаемых для каждого режима доступа к файлу.
Random Номер записи, которая будет считана или записана следующей.
Binary, Output, Append, Input Номер байта, с которого начинается выполнение следующей операции ввода/вывода. Первому байту файла соответствует 1, второму 2 и т.п.
Функция EOF - Возвращает значение типа Integer содержащее логическое значение True при достижении конца файла.
EOF(номерФайла)
Обязательный аргумент номерФайла является выражением типа Integer, содержащим любой допустимый номер файла.
С помощью функции EOF можно избежать ошибок, возникающих при попытках чтения или записи после достижения конца файла.
Функция EOF возвращает значение False до тех пор, пока не будет достигнут конец файла. При использовании с файлами, открытыми в режиме Random или Binary, функция EOF возвращает значение True, если последней выполненной инструкции Get не удалось считать целую запись; в противном случае возвращается значение False.
Для файлов, открытых для доступа в режиме Binary, попытка чтения файла с помощью функции Input до возвращения функцией EOF значения True приводит к ошибке. При чтении двоичных файлов с помощью функции Input следует вместо функции EOF использовать функции LOF и Loc или использовать с функцией EOF инструкцию Get.
Ввод/вывод в файлы различных типов доступа.
Последовательный доступ к файлам:
Последовательный доступ лучше применять к файлам, состоящим только из текста, созданного в текстовом редакторе. В них невыгодно хранить числа, так как в строковом виде они занимают больше места, чем в числовом.
Файлы, открытые для последовательного доступа, допускают следующие операции:
ввод символов в файл (Input);
вывод символов из файла (Output);
добавление символов в файл (Append).
Чтобы открыть файл для последовательного доступа, следует использовать оператор Open:
Open pathname For [Input | Output | Append] As filenum [Len = Buffersize]
Когда последовательный файл открывается для ввода (Input), файл должен существовать, иначе возникнет ошибка. Однако при попытке открыть несуществующий файл для операций вывода (Output) или добавления (Append) оператор Open сначала создает файл, а затем открывает его. Номер файла filenum является обязательным и может быть получен с помощью функции FreeFile. Необязательный параметр Len задает число символов в буфере для операций копирования данных из файла в приложение. Чем больше буфер, тем реже производятся обращения к диску. После открытия файла для операций Input, Output или Append его надо закрыть с помощью оператора Close, прежде чем открывать для операции другого типа.
Для редактирования файла сначала надо прочитать его содержимое в программные переменные, затем изменить переменные и записать их содержимое обратно в файл. Чтобы получить содержимое текстового файла, следует открыть его для операции последовательного ввода (Input). Затем используют оператор Line Input #, Input () или Input #, чтобы скопировать файл в программные переменные. Существуют операторы и функции, которые для последовательных файлов читают и записывают один символ или одну строку за одну операцию. Следующий фрагмент читает файл строка за строкой:
Dim Lines As String, NextLine As String
Do Until EOF (FileNum)
Line Input # FileNum, NextLine
Lines = Lines + NextLine + Chr(13) + Chr(10)
Loop
Оператор Line Input # распознает последовательность символов CR/LF, но не включает их в переменную. О сохранении этих символов должен позаботиться программист.
Можно также использовать оператор Input #, который читает числа и/или строковые выражения, записанные в файл. Например, для чтения строки адреса можно использовать следующий оператор:
Input # FileNum, name, street, city, zip, country
Можно использовать функцию Input () для копирования любого числа символов из файла в переменную при условии, что они могут поместиться в этой переменной:
Lines = Input (n, FileNum)
Чтобы скопировать целый файл в переменную, следует использовать функцию InputB. Так как она возвращает строку в коде ANSI, для преобразования ее в строку UNICODE надо применять функцию StrConv:
Lines = StrConv(InputB(LOF(FileNum), FileNum), vbUnicode)
Для записи строк в файл следует открыть его для последовательного вывода (Output) или добавления (Append), а затем использовать оператор Print #, например:
Print #FileNum, Text
Существует также оператор Write #, который записывает список чисел и/или строковых выражений в файл. Он автоматически отделяет каждое выражение запятой и заключает строковые выражения в кавычки:
AnyString = "AnyChars" : AnyNum = 12345
Write #FileNim, AnyString, AnyNum
Результат будет выглядеть так:
"AnyChars",12345
Рассмотрим более полный пример, в котором читается текстовый файл, ищутся строки, начинающиеся с одинаковой буквы, и выводятся в другой текстовый файл:
Sub пример12()
Dim first() As String, s() As String
Dim n As Integer, i As Integer, k As Integer
Dim fn As Integer, x As String
i = 1: k = 0
fn = FreeFile
Open "D:\input.txt" For Input As fn
Do While Not EOF(fn)
ReDim Preserve s(1 To i)
ReDim Preserve first(1 To i)
Line Input #fn, s(i)
first(i) = Left(s(i), 1)
i = i + 1
Loop
Close #fn
i = i - 1
fn = FreeFile
Open "D:\output.txt" For Output As fn
For n = 1 To i
If n <> i Then
For k = n + 1 To i
If first(k) = first(n) Then
Print #fn, s(n), s(k)
End If
Next k
End If
Next n
Close #fn
End Sub
Произвольный доступ к файлам:
Байты в файлах произвольного доступа формируют записи, каждая из которых содержит одно или более полей. Запись с одним полем соответствует любому стандартному типу. Запись с несколькими полями соответствует определяемому пользователем типу. Например, тип Worker, определяемый ниже, создает 19 байтные записи, которые состоят из трех полей:
Type Worker
LastName As String * 10
Title As String * 7
Rank As String * 2
End Type
После определения типа, соответствующего записи, следует объявить другие переменные, которые необходимы в процессе открытия файла для произвольного доступа, например:
'Переменная записей
Public Employee As Worker
'Текущая запись
Public Position As Long
'Номер последней записи в файле
Public LastRecord As Long
Открыть файл для производного доступа можно с помощью следующего синтаксиса оператора Open:
Open pathname [ For Random] As filenumber Len = reclength
Так как типом доступа по умолчанию является произвольный (random), ключевые слова For Random не обязательны.
Выражение Len = reclength задает размер каждой записи в байтах. Заметим, что каждая строковая переменная в VBA хранится в формате Unicode, и надо задать длину этой строки. Если reclength меньше, чем действительная длина записываемой в файл записи, генерируется ошибка. Если reclength больше действительной длины записи, то запись сохраняется, но дисковое пространство при этом будет расходоваться нерационально.
Для открытия файла можно использовать следующий код:
Dim FileNum As Integer, RecLength As Long, Employee As Person
' Вычисляем длину каждой записи.
RecLength = LenB (Employee)
' Получаем следующий доступный номер файла.
FileNum = FreeFile
' Открываем новый файл оператором Open.
Open "MYFILR.FIL" For Random As FileNum Len = RecLength
Чтобы отредактировать файл произвольного доступа, сначала следует считать записи из файла в программные переменные, затем изменить значения переменных и записать переменные обратно в файл. В следующих разделах обсуждается, как редактировать файлы, открытые для произвольного доступа.
Для копирования записей в переменные следует использовать оператор Get. Например, чтобы скопировать запись из файла Employee Records в переменную Employee, можно использовать следующий код:
Get FileNum, Position, Employee
В этой строке Employee содержит номер, который оператор Open использовал для открытия файла; Position содержит номер записи, которая копируется; переменная Employee, объявленная с определенным пользователем типом Worker, получает содержимое записи.
Добавлять или изменять записи в файлах, открытых для произвольного доступа, можно с помощью оператора Put. Чтобы заменить запись, следует использовать оператор Put, задавая положение записи в файле, например:
Put # FileNum, Position, Employee
Этот код заменит запись с номером, заданным переменной Position, данными из переменной Employee.
Чтобы добавить новые записи в конец файла, открытого для произвольного доступа, следует использовать оператор Put, показанный в предыдущем фрагменте кода. Для этого надо установить значение переменной , Position равным на единицу больше номера последней записи в файле. Например, чтобы добавить новую запись в файл, содержащий пять записей, следует установить переменную Position равной 6.
Следующий оператор добавляет запись в конец файла:
LastRecord = LastRecord + 1
Put #FileNum, LastRecord, Employee
Можно удалить запись, очистив ее поля, но тогда запись все еще останется в файле. Не стоит просто очищать записи в файле, так как, оставаясь в нем, они расходуют пространство и служат помехой при выполнении операций последовательного доступа. Лучше скопировать остающиеся в файле записи в новый файл, и затем удалить старый.
Чтобы удалить запись в файле произвольного доступа, следует:
1. Создать новый файл.
2. Скопировать все необходимые из исходного файла в этот новый файл.
3. Закрыть исходный файл и с помощью оператора Kill удалить его.
4. С помощью оператора Name переименовать новый файл, дав ему имя исходного файла.
Доступ к двоичным файлам:
Двоичный доступ дает возможность полного управления файлом, так как байты в файле могут представлять собой все что угодно. Например, можно сократить дисковое пространство, построив записи переменной длины. Двоичный доступ следует использовать, если важно сохранить небольшой размер файла.
Чтобы открыть файл для двоичного доступа, используют следующий синтаксис Open:
Open pathname For Binary As filename
Отличие от оператора для произвольного доступа заключается в отсутствии указания длины записи с помощью предложения Len = RecLength. Будучи включено в оператор открытия двоичного файла, оно просто игнорируется, поскольку предполагается, что записи имеют произвольную длину. Отсюда следует, что невозможно организовать доступ к записям в произвольном порядке, а только последовательно, определяя длину каждой записи. В то же время можно непосредственно обращаться к каждому байту в файле.