Просмотр содержимого DBF файла с возможностью печати его структуры.
Поддержка как DOS, так и Windows кодировки.
Поддержка как DOS, так и Windows кодировки.
По роду своей деятельности часто приходится иметь дело с форматом «DBF». Причем работа ведется на управляемых формах.
Т.к. для модального режима внешний отчет уже написан, то чтобы каждый раз не менять режим, я переделал его для управляемых форм.
Надеюсь, кому — либо пригодится.
Отчет в прикреплении.
Исходный код:
&НаКлиенте
Перем База;
&НаКлиенте
Функция ДиалогОткрытияФайлаDBF()
СтандартнаяОбработка = Ложь;
ДиалогОткрытияФайла = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
ДиалогОткрытияФайла.Фильтр = "Файлы DBF(*.dbf)|*.dbf|";
ДиалогОткрытияФайла.ПроверятьСуществованиеФайла = Истина;
ДиалогОткрытияФайла.МножественныйВыбор = Ложь;
ДиалогОткрытияФайла.Заголовок = "Выберите файл dbf (Формат - Data Base III)";
Если ДиалогОткрытияФайла.Выбрать() Тогда
Возврат ДиалогОткрытияФайла.ПолноеИмяФайла;
Иначе
Возврат Неопределено;
КонецЕсли;
КонецФункции
&НаКлиенте
Процедура ДиалогСВопросом(ТекстВопроса, ЗаголовокВопроса, РежимДиалога)
Оповещение = Новый ОписаниеОповещения("ПослеЗакрытияВопроса", ЭтотОбъект);
ПоказатьВопрос(Оповещение,
ТекстВопроса,
РежимДиалога,
0,
КодВозвратаДиалога.Да,
ЗаголовокВопроса
);
КонецПроцедуры
&НаКлиенте
Процедура ПослеЗакрытияВопроса(Результат, Параметры) Экспорт
Если Результат = КодВозвратаДиалога.Да Тогда
ЗагрузкаДанных();
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ДобавитьПоляВТЗ(МассивСтруктур)
/////////////////////////////////////////////////////////
//Преобразуем массив структур в исходную таблицу значений
ИсхТЗ = Новый ТаблицаЗначений;
Для Каждого ЭлементМассива Из МассивСтруктур Цикл
//Если еще не добавили, добавляем колонки
Если ИсхТЗ.Колонки.Количество() = 0 Тогда
Для Каждого ЗначениеСтруктуры Из ЭлементМассива Цикл
ИсхТЗ.Колонки.Добавить(ЗначениеСтруктуры.Ключ);
КонецЦикла;
КонецЕсли;
//Добавляем данные в таблицу
НоваяСтрока = ИсхТЗ.Добавить();
Для Каждого ЗначениеСтруктуры Из ЭлементМассива Цикл
НоваяСтрока[ЗначениеСтруктуры.Ключ] = ЗначениеСтруктуры.Значение;
КонецЦикла;
КонецЦикла;
/////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////
//Почистим таблицу на форме
ТЗНаФорме.Очистить();
МассивУдаляемыхРеквизитов = Новый Массив;
РеквизитыТЗ = ПолучитьРеквизиты("ТЗНаФорме");
Если РеквизитыТЗ.Количество() > 0 Тогда
Для Каждого Реквизит Из РеквизитыТЗ Цикл
МассивУдаляемыхРеквизитов.Добавить("ТЗНаФорме." + Реквизит.Имя);
КонецЦикла;
ЭтаФорма.ИзменитьРеквизиты(,МассивУдаляемыхРеквизитов);
Для Каждого Реквизит Из РеквизитыТЗ Цикл
УдаляемыйЭлемент = Элементы.Найти("ТЗНаФорме_" + Реквизит.Имя);
Если УдаляемыйЭлемент <> Неопределено Тогда
Элементы.Удалить(УдаляемыйЭлемент);
КонецЕсли;
КонецЦикла;
КонецЕсли;
/////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////
//Создаем массив реквизитов - колонок для таблицы значений на форме
МассивРеквизитов = Новый Массив;
Для Каждого Колонка Из ИсхТЗ.Колонки Цикл
МассивРеквизитов.Добавить(Новый РеквизитФормы(Колонка.Имя, Колонка.ТипЗначения, "ТЗНаФорме", Колонка.Заголовок));
КонецЦикла;
/////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////
//Выводим добавленные колонки на форму
ЭтаФорма.ИзменитьРеквизиты(МассивРеквизитов);
ЗначениеВРеквизитФормы(ИсхТЗ, "ТЗНаФорме");
Таблица = Элементы.ТЗНаФорме;
Таблица.Отображение = ОтображениеТаблицы.Список;
Для Каждого Колонка Из ИсхТЗ.Колонки Цикл
НовыйЭлемент = Элементы.Добавить("ТЗНаФорме_" + Колонка.Имя, Тип("ПолеФормы"), Таблица);
НовыйЭлемент.Вид = ВидПоляФормы.ПолеВвода;
НовыйЭлемент.ПутьКДанным = "ТЗНаФорме." + Колонка.Имя;
КонецЦикла;
/////////////////////////////////////////////////////////
КонецПроцедуры
&НаКлиенте
Процедура ОсновныеДействияФормыОткрыть(Кнопка)
ИмяФайла = ДиалогОткрытияФайлаDBF();
Если ИмяФайла = Неопределено Тогда
Возврат;
КонецЕсли;
База = Новый XBase;
Попытка
База.ОткрытьФайл(ИмяФайла);
Исключение
Сообщить("Произошла ошибка при обращение к файлу dbf:" + Символы.ПС + ОписаниеОшибки());
Возврат;
КонецПопытки;
Если ФДОС=Истина Тогда
База.Кодировка=КодировкаXBase.OEM;
Иначе
База.Кодировка=КодировкаXBase.ANSI;
КонецЕсли;
База.ОтображатьУдаленные = Истина;
Записей = База.КоличествоЗаписей();
Если (Записей > 10000) И (Ф100 = Ложь) Тогда
Режим = РежимДиалогаВопрос.ДаНет;
ТекстВопроса = "Количество записей в файле " + Записей + ". Продолжить?";
ДиалогСВопросом(ТекстВопроса, "Длительная загрузка данных!", РежимДиалогаВопрос.ДаНет);
Иначе
ЗагрузкаДанных();
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ЗагрузкаДанных()
Записей = База.КоличествоЗаписей();
МассивСтруктур = Новый Массив;
Для А=1 По Записей Цикл
Состояние("Выводится запись "+А+" из "+Записей, Цел(А/Записей*100));
Если Ф100 И (А>100) Тогда
Прервать;
КонецЕсли;
База.Перейти(А);
СтруктураКолонок = Новый Структура;
Если База.ЗаписьУдалена()=Истина Тогда
СтруктураКолонок.Вставить("Удален","•");
Иначе
СтруктураКолонок.Вставить("Удален"," ");
КонецЕсли;
СтруктураКолонок.Вставить("N", А);
Для Каждого Поле из База.Поля Цикл
СтруктураКолонок.Вставить(Поле.Имя, База.ПолучитьЗначениеПоля(Поле.Имя));
КонецЦикла;
МассивСтруктур.Добавить(СтруктураКолонок);
КонецЦикла;
ДобавитьПоляВТЗ(МассивСтруктур);
База.ЗакрытьФайл();
КонецПроцедуры
&НаСервере
Функция ПолучитьМакетНаСервере(ИмяМакета)
ТекОбъект = РеквизитФормыВЗначение("Отчет");
Возврат ТекОбъект.ПолучитьМакет(ИмяМакета);
КонецФункции
&НаКлиенте
Процедура ОсновныеДействияФормыСтруктура(Кнопка)
Если ИмяФайла = "" Тогда
Возврат;
КонецЕсли;
База = Новый XBase;
База.ОткрытьФайл(ИмяФайла);
МассивПолей = Новый Массив;
Для Каждого Поле Из База.Поля Цикл
МассивПолей.Добавить(Новый Структура("Имя, Тип, Длина, Точность", Поле.Имя, Поле.Тип, Поле.Длина, Поле.Точность));
КонецЦикла;
Таб = Новый ТабличныйДокумент;
ОсновныеДействияФормыНаСервере(МассивПолей, Таб);
База.ЗакрытьФайл();
Таб.Показать("Структура файла DBF");
КонецПроцедуры
&НаСервере
Процедура ОсновныеДействияФормыНаСервере(МассивПолей, Таб)
Макет = ПолучитьМакетНаСервере("Структура");
Секция = Макет.ПолучитьОбласть("Шапка");
Секция.Параметры.ИмяФайла = ИмяФайла;
Таб.Вывести(Секция);
Секция = Макет.ПолучитьОбласть("Повтор");
Для Каждого Поле Из МассивПолей Цикл
Секция.Параметры.Заполнить(Поле);
Таб.Вывести(Секция);
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура ЗакрытьФорму(Команда)
ЭтаФорма.Закрыть();
КонецПроцедуры
&НаКлиенте
Процедура ПриОткрытии(Отказ)
ИмяФайла="";
ФДОС = Истина;
КонецПроцедуры
Было бы хорошо, чтобы можно было редактировать и сохранять. Просто смотреть можно и в Excel.
(1) AleksSF, спасибо за совет, я думаю в ближайшее время добавлю и сохранение. Просто пока со временем туго.
Есть несколько комментариев:
1. Загрузка всего файла в память не всегда может быть нужна (и не всегда возможна). Особенно для отображения в управляемой форме. Нужно копать в сторону загрузки частями.
2. Всю обработку можно (и нужно) выполнять на клиенте. Зачем нужна передача на сервер, зачем массив структур?
3. Почему табличный документ? Вывод в виде таблицы на форму был бы логичнее.
4. Не проверяли скорость работы через ADO?
(3) ufedor, вся проблема в использовании таблицы значений — ее создание и редактирование полей на клиенте не поддерживается, так-же из-за этого я использую передачу массива структур. Насчет способов вывода (в качестве табличного документа или в виде таблицы), признаюсь, особо не заморачивался — что первым пришло в голову, то и применил.
По поводу загрузки частями полностью с Вами согласен.
Скорость не проверял.