Показать сообщение отдельно
Старый 17.09.2010, 21:22   #49  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,651 / 1158 (42) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Извиняюсь, что поднял старую тему, просто что-то поиском не нашел ответа на вроде бы очевидный вопрос, как при экспорте в Excel через RecordSet оставить ячейки не заполненными? Ну, например, если не указана дата, то в ячейке Excel должно быть пусто, а не 00.01.1900.

Разумеется, покопавшись в справке довольно быстро нашел ответ. Но, может, еще кому пригодится.

Суть сводится к тому, что соответствующее поле RecordSet должно содержать значение NULL на момент создания новой строки. Вообще-то, по умолчанию, при создании новой строки в RecordSet, если явно не указано значение, то и предпринимается попытка присвоить значение NULL. Однако, опять же по умолчанию, поле RecordSet создается с невозможностью принимать значение NULL и, как следствие, присваивает "пустое" значение

Допустимость использования значения NULL задается 4 параметром в методе Fields.Append(). 3 параметр - это размерность поля в байтах. Есть еще 5 параметр - значение по умолчанию, но практического смысла в данном случае 5 параметр не имеет.

Тогда код будет выглядеть примерно так

X++:
static void Job_ADORecordSet2Excel_EmptyCells(Args _args)
{
    Com comRecordSet;
    Com comFields;
    Com comField;

    ComExcelDocument_RU excel;
    Com                 comRange;
    ;

    #define.adFldIsNullable(32)  // Поле может принимать значение NULL
    #define.adFldMayBeNull(64) // Из поля можно прочитать значение NULL

    comRecordSet = new COM('ADODB.Recordset');
    // формируем структуру Recordset
    // где каждое поле может принимать значение NULL
    comFields = comRecordSet.Fields();
    comFields.Append("FieldStr",    COMVariantType::VT_BSTR,    50, #adFldIsNullable + #adFldMayBeNull);
    comFields.Append("FieldReal",   COMVariantType::VT_R8,      8,  #adFldIsNullable + #adFldMayBeNull);
    // Если нужна только даты без части со временем, то следует указать значение 133
    // Такого значения нет в Base Enum с именем COMVariantType
    comFields.Append("FieldDate",   COMVariantType::VT_DATE,    8,  #adFldIsNullable + #adFldMayBeNull);

    // Открываем RecordSet для заполнения
    comRecordSet.open();

    // Формируем первую строку
    comRecordSet.AddNew();

    // Наполняем ее данными для сравнения
    comField = comFields.Item("FieldStr");
    comField.value(comVariant::createFromStr("Первая строка"));

    comField = comFields.Item("FieldReal");
    comField.value(comVariant::createFromReal(123.456));

    comField = comFields.Item("FieldDate");
    comField.value(comVariant::createFromDate(systemDateGet()));

    // Формируем вторую строку
    // В которой нет никаких данных. Ячейки будут пустыми
    comRecordSet.AddNew();

    // Формируем третью строку
    comRecordSet.AddNew();

    // Наполняем ее данными для сравнения
    comField = comFields.Item("FieldStr");
    comField.value(comVariant::createFromStr("Третья строка"));

    comField = comFields.Item("FieldReal");
    comField.value(comVariant::createFromReal(789.012));

    comField = comFields.Item("FieldDate");
    comField.value(comVariant::createFromDate(systemDateGet()+2));

    // Открываем Excel с пустым листом и сразу делаем его видимым
    excel = new ComExcelDocument_RU();
    excel.newFile("",true);

    // Определяем ячейку, откуда будет осуществляться вывод
    comRange = excel.findRange("A1");

    // Выводим данные
    comRange.CopyFromRecordset(comRecordSet);

}


Собственно, это все работает, если ничего не вводить в поле RecordSet. Но, к сожалению не нашел, а как записать в поле RecordSet значение null ? Единственный, не очень хороший вариант - это присвоение исходного (оригинального) значения, исходя из предположения, что это значение NULL

X++:
    comField = comFields.Item("FieldDate");
    comField.value(comField.OriginalValue());
За это сообщение автора поблагодарили: S.Kuskov (5).