Как записать значение в поле типа MEMO в DBF-файл через OLE DB?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

Работа с файлами формата DBF (dBase) остается актуальной задачей при интеграции 1С с внешними системами, оборудованием или старыми базами данных. Одной из наиболее сложных проблем является запись данных в поля типа MEMO (длинный текст). Обычные SQL-запросы через метод Execute часто терпят неудачу, когда длина строки превышает 254 символа. В этой статье мы подробно разберем, почему это происходит и как правильно организовать запись больших объемов данных с использованием провайдера Visual FoxPro (VFPOLEDB).

Почему возникает ошибка при прямой записи?

Рассмотрим ситуацию: вы пытаетесь выполнить стандартный SQL-запрос INSERT INTO, передавая длинную строку непосредственно в тексте команды. Проанализируем типичную ошибку: Command contains unrecognized phrase/keyword или Syntax error. Причина кроется в архитектуре SQL-движка Visual FoxPro: строковые константы (литералы), заключенные в кавычки, имеют жесткое ограничение по длине — обычно это 254 или 255 символов.

Если ваша переменная ЗаписьМ содержит XML-структуру или длинное описание товара, парсер драйвера просто не сможет обработать такую длинную строку внутри текста команды. Чтобы обойти это ограничение, нам необходимо передавать данные не как текст команды, а как параметры.

Решение №1: Использование объекта ADODB.Command и параметров

Самый надежный и профессиональный способ записи в поля типа MEMO — это использование объекта ADODB.Command. Этот метод позволяет передавать данные во внутренний буфер драйвера напрямую, минуя парсер SQL-текста. Разберем этот процесс по шагам.

Сначала создадим соединение и саму таблицу. Обратите внимание на тип поля M (Memo) в команде CREATE TABLE:


Соединение = Новый COMОбъект("ADODB.Connection");
Соединение.ConnectionString = "Provider=vfpoledb.1;Data Source=" + КаталогДляВыгрузки + ";";
Соединение.Mode = 3; // adModeReadWrite
Соединение.Open();

// Создаем таблицу с полем CODE2 (строка) и INFO (Memo)
Соединение.Execute("CREATE TABLE Calculation.dbf (CODE2 C(10) NOT NULL, INFO M NOT NULL)");

Теперь подготовим команду для вставки данных. Вместо конкретного значения в SQL-запросе мы ставим знак вопроса ?, который служит плейсхолдером для параметра:


// Создаем объект команды
Command = Новый COMОбъект("ADODB.Command");
Command.ActiveConnection = Соединение;
Command.CommandText = "INSERT INTO Calculation (CODE2, INFO) VALUES ('" + Строка(КодТовара) + "', ?)";

// Создаем и настраиваем параметр для поля MEMO
// Используем тип 201 (adLongVarChar) для длинных строк или 129 (adChar)
param = Command.CreateParameter("PINFO", 201, 1, 1000000, ЗначениеМемоПоля);

// Добавляем параметр в коллекцию команды
Command.Parameters.Append(param);

// Выполняем запись
Command.Execute();
Соединение.Close();

Рассмотрим подробнее параметры метода CreateParameter:

  1. Имя параметра (например, "PINFO") — техническое имя.
  2. Тип данных (Type): значение 201 соответствует adLongVarChar. Это наиболее подходящий тип для Memo-полей. Иногда используют 129 (adChar), но для очень больших текстов лучше выбирать Long-типы.
  3. Направление (Direction): 1 означает adParamInput (входной параметр).
  4. Размер (Size): укажите максимальный предполагаемый размер строки (например, 1 000 000 символов).
  5. Значение (Value): сама ваша длинная строка из 1С.

Решение №2: Использование ADODB.Recordset

Если работа с объектом Command кажется избыточной, можно воспользоваться объектом Recordset. Этот метод удобен тем, что драйвер сам управляет записью в связанные файлы .fpt (в которых физически хранятся данные MEMO-полей).

Проанализируем пример записи через Recordset:


RecordSet = Новый COMОбъект("ADODB.Recordset");
// Открываем таблицу. 1 - adOpenKeyset, 3 - adLockOptimistic
RecordSet.Open("SELECT * FROM Calculation", Соединение, 1, 3);

RecordSet.AddNew();
RecordSet.Fields("CODE2").Value = "001";
RecordSet.Fields("INFO").Value = ЗаписьМ; // 1С передаст строку любой длины
RecordSet.Update();

RecordSet.Close();

Этот способ часто работает медленнее при массовой загрузке, но он гораздо стабильнее в плане обработки спецсимволов и кодировок, так как вы работаете напрямую с полями объекта базы данных.

Важные технические нюансы

При работе с MEMO-полями в формате DBF важно помнить о нескольких критических моментах, которые могут повлиять на результат:

  1. Наличие FPT-файла: Данные MEMO-полей хранятся не в самом .dbf, а в отдельном файле с расширением .fpt. Если вы переносите базу данных, всегда копируйте пару файлов (DBF + FPT) вместе. Если FPT-файл будет отсутствовать или поврежден, DBF-файл не откроется.
  2. Кодировка (CodePage): 1С работает со строками в Unicode. DBF-файлы чаще всего ожидают кириллицу в кодировке Windows-1251. Чтобы избежать появления "кракозябр", в строку подключения (ConnectionString) рекомендуется добавить параметр Extended Properties="Codepage=1251;" или CharSet=1251;.
  3. Ограничение на чтение: Если вы потом будете читать эти данные через другие драйверы (например, стандартный Microsoft dBase Driver), помните, что не все они корректно поддерживают MEMO-поля Visual FoxPro. Рекомендуется использовать VFPOLEDB как для записи, так и для чтения.
  4. Раздувание файла (Bloat): При частом обновлении записей в Memo-полях файл .fpt быстро растет, так как старые блоки данных не удаляются автоматически. В полноценном FoxPro для этого используется команда PACK, но через OLE DB это сделать сложно (требуется эксклюзивный доступ). Иногда проще пересоздать файл при полной выгрузке.

Подведем итог: для успешной записи длинных текстов в DBF используйте связку ADODB.Command и ADODB.Parameter. Это снимет все ограничения на длину строки и обеспечит корректную передачу данных в поле типа M.

← На главную