При работе с программными продуктами 1С:Предприятие, особенно после обновления платформы, пользователи могут столкнуться с проблемой, когда экспорт отчетов, содержащих изображения (например, прайс-листов с фотографиями номенклатуры), приводит к созданию файлов Excel слишком большого объема. Такая ситуация возникла у пользователей 1С:Управление торговлей 11 после обновления платформы до версии 8.3.20.1674, когда ранее происходившее автоматическое сжатие картинок прекратилось. Давайте разберем причины этой проблемы и рассмотрим возможные решения.
Прежде чем перейти к методам сжатия, выясним, почему эта проблема возникает. Рассмотрим подробнее несколько ключевых факторов, влияющих на размер экспортируемых файлов:
Понимание этих причин поможет нам выбрать наиболее эффективный подход к решению проблемы.
Один из самых простых и эффективных способов уменьшить размер файла с прайс-листом после экспорта из 1С – это воспользоваться встроенной функцией сжатия изображений в самом Microsoft Excel. Этот метод работает независимо от версии платформы 1С и не требует программных изменений в конфигурации.
Рассмотрим, как вы можете выполнить это вручную после сохранения прайс-листа в формате .xls или .xlsx:
Этот способ является самым простым и доступным для конечного пользователя, не требующим вмешательства в конфигурацию 1С.
Если требуется автоматизировать процесс сжатия или обеспечить, чтобы изображения уже в 1С хранились в оптимизированном размере для отчетов, мы можем программно уменьшать их размер и разрешение перед использованием в отчете или перед сохранением в базу данных. Этот метод требует доработки конфигурации 1С.
УстановитьРазмер()В 1С есть возможность программно управлять размерами изображений. Для этого используется объект Картинка и его метод УстановитьРазмер(). Этот метод позволяет изменить размеры картинки по вертикали и горизонтали, при этом можно сохранить пропорции.
ДвоичныеДанныеФайлов, как это указано в исходном запросе автора темы.Картинка: Из полученных двоичных данных мы создаем объект Картинка.УстановитьРазмер() для уменьшения размеров. Мы можем задать новую ширину или высоту, и 1С пропорционально изменит вторую величину.Картинка, которые будут содержать уже уменьшенное изображение. Эти данные затем могут быть использованы для вставки в табличный документ отчета.Рассмотрим пример кода, который демонстрирует этот подход. Этот код может быть интегрирован в модуль отчета или обработку, формирующую прайс-лист:
// Предположим, у нас есть ДвоичныеДанныеФайла из запроса
// ДвоичныеДанныеФайлов.ДвоичныеДанныеФайла КАК КартинкаДвоичныеДанные
// и мы хотим получить объект Картинка
// Из запроса СКД мы получаем ДвоичныеДанныеФайла
// Пример извлечения двоичных данных и их обработки
Функция ПолучитьСжатуюКартинкуДляОтчета(ДвоичныеДанныеФайла, МаксимальнаяШирина = 200, МаксимальнаяВысота = 200)
Если ТипЗнч(ДвоичныеДанныеФайла) <> Тип("ДвоичныеДанные") Тогда
Возврат Неопределено; // или выдать ошибку, или вернуть исходные данные
КонецЕсли;
Попытка
КартинкаОбъект = Новый Картинка(ДвоичныеДанныеФайла);
Исключение
Возврат Неопределено; // Не удалось создать картинку из двоичных данных
КонецПопытки;
Если КартинкаОбъект.Ширина > МаксимальнаяШирина ИЛИ КартинкаОбъект.Высота > МаксимальнаяВысота Тогда
// Определяем новые размеры с сохранением пропорций
КоэффициентШирины = МаксимальнаяШирина / КартинкаОбъект.Ширина;
КоэффициентВысоты = МаксимальнаяВысота / КартинкаОбъект.Высота;
Если КоэффициентШирины < КоэффициентВысоты Тогда
// Ограничиваем по ширине
НоваяШирина = МаксимальнаяШирина;
НоваяВысота = Цел(КартинкаОбъект.Высота * КоэффициентШирины);
Иначе
// Ограничиваем по высоте
НоваяВысота = МаксимальнаяВысота;
НоваяШирина = Цел(КартинкаОбъект.Ширина * КоэффициентВысоты);
КонецЕсли;
// Применяем новые размеры
КартинкаОбъект.УстановитьРазмер(НоваяШирина, НоваяВысота);
КонецЕсли;
Возврат КартинкаОбъект; // Возвращаем объект Картинка уменьшенного размера
КонецФункции
// Пример использования в процедуре формирования отчета
// ...
// ТабличныйДокумент = Новый ТабличныйДокумент;
// ...
// Если РезультатЗапроса.Следующий() Тогда
// ОбластьМакета.Параметры.Номенклатура = РезультатЗапроса.Номенклатура;
//
// КартинкаДляОтчета = ПолучитьСжатуюКартинкуДляОтчета(РезультатЗапроса.КартинкаДвоичныеДанные, 150, 150);
// Если КартинкаДляОтчета <> Неопределено Тогда
// ТабличныйДокумент.Картинки.Добавить(КартинкаДляОтчета, ОбластьМакета.Область("B2:C5"), ОбластьМакета); // Пример вставки
// КонецЕсли;
//
// ТабличныйДокумент.Вывести(ОбластьМакета);
// КонецЕсли;
// ...
Важно отметить, что УстановитьРазмер() изменяет только разрешение картинки. Она не выполняет JPEG-сжатие, которое позволяет значительно уменьшить размер файла за счет потери качества. Для JPEG-сжатия могут потребоваться внешние компоненты или библиотеки.
Существуют готовые модули и обработки для 1С, которые позволяют массово сжимать изображения в базе данных. Эти инструменты часто используют внешние библиотеки (например, ImageMagick или внутренние механизмы 1С для работы с графикой) для оптимизации изображений. Они могут:
Такие решения могут быть полезны, если у вас в базе хранится большое количество высококачественных изображений, которые не используются в исходном качестве для прайс-листов и занимают много места. При этом важно убедиться, что оригинальные изображения в справочнике номенклатуры (если они должны оставаться в исходном качестве) либо не затрагиваются, либо сохраняются резервные копии.
Более сложным, но потенциально мощным подходом является программное управление Microsoft Excel через COM-объект из 1С. Этот метод позволяет автоматизировать действия, которые мы выполняем вручную в Excel.
Основная идея заключается в следующем:
Excel.Application.Однако прямой программный доступ к функции "Сжать рисунки" (Compress Pictures) в Excel через VBA (а значит, и через COM-объект из 1С) может быть неочевиден или ненадежен. Макросы, созданные записью действий пользователя в Excel, не всегда включают необходимые команды для сжатия, поскольку это часто является частью более высокоуровневых операций. В некоторых случаях могут использоваться методы, имитирующие нажатия клавиш (SendKeys), но этот подход крайне ненадежен и не рекомендуется для использования в продуктивных системах из-за зависимости от фокуса окна и скорости выполнения.
Вместо прямого вызова функции сжатия, мы можем попробовать управлять свойствами каждого изображения в Excel. Например, можно перебирать все объекты Shape (которые включают изображения) на листах Excel и пытаться программно изменять их свойства. Однако, API Excel через COM не предоставляет прямого метода для "сжатия" изображения в том смысле, как это делает пользовательская функция. Чаще всего, через COM можно управлять размером, позицией, иногда качеством сохранения, но не запускать процесс перекодирования и сжатия, который происходит при использовании кнопки "Сжать рисунки".
В контексте 1С и табличных документов, для сохранения исходных размеров и разрешения картинки при экспорте в Excel, можно установить для свойства РазмерКартинки в табличном документе значение РазмерКартинки.Растянуть или РазмерКартинки.Авто. Это влияет на то, как картинка масштабируется в ячейке, но не на ее фактические двоичные данные, которые передаются в Excel.
Пример работы с COM-объектом Excel для открытия файла (без конкретного кода сжатия, так как он сложен и ненадежен):
// ... код формирования ТабличногоДокумента и сохранения его во временный файл
ИмяФайлаExcel = КаталогВременныхФайлов() + "ПрайсЛист.xlsx";
ТабличныйДокумент.Записать(ИмяФайлаExcel, ТипФайлаТабличногоДокумента.XLSX);
// Создаем объект Excel
Попытка
ExcelПриложение = Новый COMОбъект("Excel.Application");
ExcelПриложение.Visible = Истина; // Или Ложь, если не хотим показывать пользователю
КнигаExcel = ExcelПриложение.Workbooks.Open(ИмяФайлаExcel);
// Здесь может быть код для перебора листов и объектов Shape (рисунков)
// и попытки изменить их свойства, но прямое сжатие через COM не всегда доступно.
// Например, можно попробовать изменить размер или свойства объекта.
// КнигаExcel.Save(); // Сохранить изменения
// КнигаExcel.Close();
// ExcelПриложение.Quit();
Исключение
Сообщить("Ошибка при работе с COM-объектом Excel: " + ОписаниеОшибки());
КонецПопытки;
Для стабильной работы с COM-объектами Excel, особенно на сервере 1С, необходимо учитывать несколько моментов:
DCOM Microsoft Excel Application. Это часто является источником проблем при серверной работе.КнигаExcel.Close(), ExcelПриложение.Quit(), а также устанавливать переменные в Неопределено), чтобы избежать зависания процессов Excel в памяти.Учитывая сложности и ненадежность прямого программного вызова функции сжатия через COM, этот метод может быть менее предпочтительным по сравнению с предварительной оптимизацией картинок в 1С или ручным сжатием в самом Excel.
В контексте Системы Компоновки Данных (СКД), вывод картинок часто требует программной доработки, поскольку стандартными средствами конструктора СКД задача не всегда решается в полном объеме. Как правило, двоичные данные картинки можно получить запросом, как это сделал автор (ДвоичныеДанныеФайлов.ДвоичныеДанныеФайла КАК Картинка). Однако, вставить эти данные в табличный документ как полноценное изображение с нужным размером и расположением обычно приходится в процедуре ПриКомпоновкеРезультата() или аналогичной, где программно формируется табличный документ и в него вставляются картинки с помощью методов объекта ТабличныйДокумент.Картинки.Добавить(), используя объект Картинка.
Именно на этом этапе, при программной вставке, мы можем применить методы оптимизации из Решения 2, создавая объект Картинка из двоичных данных и уменьшая его размер до вставки в табличный документ.
Мы выяснили, что проблема большого размера Excel-файлов с прайс-листами, содержащими картинки, после экспорта из 1С, особенно после обновления платформы, является распространенной. Наиболее простым и доступным решением для конечного пользователя является использование встроенной функции "Сжать рисунки" непосредственно в Microsoft Excel после экспорта. Это позволяет быстро и эффективно уменьшить размер файла без необходимости модификации конфигурации 1С.
Для более глубокой и автоматизированной оптимизации мы рассмотрели варианты программного сжатия картинок в 1С с использованием объекта Картинка и метода УстановитьРазмер(), а также возможность использования специализированных внешних обработок. Эти методы требуют доработки конфигурации, но позволяют контролировать размер изображений еще до формирования отчета.
Наконец, мы обсудили возможности и ограничения управления Excel через COM-объект. Хотя этот метод потенциально позволяет автоматизировать многие действия, прямое вызов функции сжатия изображений через COM является сложным и ненадежным, поэтому рекомендуется использовать его с осторожностью или для других задач управления Excel.
Выбор конкретного решения будет зависеть от ваших требований к степени автоматизации, наличию ресурсов для доработки 1С и приемлемости ручных операций после экспорта.