commit b1bc06b782276ef672143b1f88e8090e568cac12 Author: Dmitry <b4tm4n@mail.ru> Date: Thu May 5 14:52:57 2022 +0300 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b3612c1 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.e[pr]f diff --git a/Word2MXL.xml b/Word2MXL.xml new file mode 100644 index 0000000..baa325a --- /dev/null +++ b/Word2MXL.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.14"> + <ExternalDataProcessor uuid="ee9bf32d-5843-4fe5-8fee-d8d0772fa740"> + <InternalInfo> + <xr:ContainedObject> + <xr:ClassId>c3831ec8-d8d5-4f93-8a22-f9bfae07327f</xr:ClassId> + <xr:ObjectId>e0ac58c4-101e-43bf-980c-2cec65422cb6</xr:ObjectId> + </xr:ContainedObject> + <xr:GeneratedType name="ExternalDataProcessorObject.Word2MXL" category="Object"> + <xr:TypeId>108ab5d9-f862-4ba3-b561-a92116d9c234</xr:TypeId> + <xr:ValueId>a97467ca-6538-4a8c-86a4-3d2b4730e0b0</xr:ValueId> + </xr:GeneratedType> + </InternalInfo> + <Properties> + <Name>Word2MXL</Name> + <Synonym> + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Word 2 MXL</v8:content> + </v8:item> + </Synonym> + <Comment/> + <DefaultForm>ExternalDataProcessor.Word2MXL.Form.Форма</DefaultForm> + <AuxiliaryForm/> + </Properties> + <ChildObjects> + <Form>Форма</Form> + </ChildObjects> + </ExternalDataProcessor> +</MetaDataObject> \ No newline at end of file diff --git a/Word2MXL/Ext/ObjectModule.bsl b/Word2MXL/Ext/ObjectModule.bsl new file mode 100644 index 0000000..2d72767 --- /dev/null +++ b/Word2MXL/Ext/ObjectModule.bsl @@ -0,0 +1,521 @@ +Функция ВывестиДокументВордВМоксель(ИмяФайла, рСантиметр = 6.25, рШиринаСтраницы = 75) Экспорт + // источник: https://infostart.ru/1c/articles/1499795/ + комВорд = Неопределено; + комДокумент = Неопределено; + Попытка + // Для пересчётов использовать комВорд.CentimetersToPoints(ЧислоСМ) и комВорд.PointsToCentimeters(ЧислоПунктов) + //рСантиметр=6.25; // в средних символах шрифта (при необходимости пересчитывать по рДиапазон.CharacterWidth - ширина символов, константа WdCharacterWidth + //рШиринаСтраницы=75; // эмпирически, довести до ума с учётом //сообщить("стран ширина "+стран.PageWidth+", высота "+стран.PageHeight); // в пунктах, работает + + // Типовые настройки документа Ворд: + // 1.25 до номера (отступ первой строки) и 1.89 табуляция (до основного текста) + // Размеры листа А4 в сантиметрах: 21х29.7 + + комВорд = Новый COMОбъект("Word.Application"); + рПодтверждатьПреобразования = Истина; + рТолькоЧтение = Истина; + комДокумент = комВорд.Documents.Open(ИмяФайла, рПодтверждатьПреобразования, рТолькоЧтение); + + #Область Проверки + комСтраница = комДокумент.PageSetup; + Если комСтраница.TextColumns.Count > 1 Тогда + Сообщить("Текущая версия не обрабатывает многоколонные документы!"); + ЗакрытьДокумент(комДокумент); // без сохранения + ЗакрытьВорд(комВорд); + Возврат Неопределено; + КонецЕсли; + рШиринаСтраницыВорда = Окр(комВорд.PointsToCentimeters(комСтраница.PageWidth), 2); + рВысотаСтраницыВорда = Окр(комВорд.PointsToCentimeters(комСтраница.PageHeight), 2); + Если НЕ ((20 <= рШиринаСтраницыВорда и рШиринаСтраницыВорда <= 22) и (28 <= рВысотаСтраницыВорда и рВысотаСтраницыВорда <= 30)) Тогда + Сообщить("Текущая версия не обрабатывает размеры страницы, отличающиеся от А4!"); + ЗакрытьДокумент(комДокумент); // без сохранения + ЗакрытьВорд(комВорд); + Возврат Неопределено; + КонецЕсли; + #КонецОбласти + + // подготовка вывода таблиц + мКомТаблиц = Новый Массив; + Для каждого комТаблица Из комДокумент.Tables Цикл + мКомТаблиц.Добавить(Новый Структура("Начало,Конец,Таблица", комТаблица.Range.Start, комТаблица.Range.End, комТаблица)); + КонецЦикла; + + #Область ПодготовкаВыводаНумерованныхСписков + // можно, конечно, рСписок.ConvertNumbersToText(ТипНомера) - но это не лучший выход, и это изменение документа + // + соотПараграфовСписков = Новый Соответствие; + Для каждого рСписок Из комДокумент.Lists Цикл // свойство комДокумент.Lists.Count ситуационно-зависимое, не применять! + // рЛист.CountNumberedItems(); + Для каждого рПараграфСписка Из рСписок.ListParagraphs Цикл + рФорматСписка = рПараграфСписка.Range.ListFormat; + рТипСписка = рФорматСписка.ListType; // WdListType + Если рТипСписка = 0 или рТипСписка = 2 или рТипСписка = 6 Тогда + // ненумерованные и bullet игнорируем + Иначе + // заниматься иерархией с проверкой погружения (рФорматСписка.ListLevelNumber) не будем, нам достаточно проверить так: + рПредставлениеПункта = СокрЛП(рФорматСписка.ListString); + // выравнивание смотрим по первой позиции уровней (хотя можно перебирать, смотреть по позиции или по NumberFormat) + Попытка рВыравнивание = рФорматСписка.ListTemplate.ListLevels.Item(0).Alignment Исключение рВыравнивание = 0 КонецПопытки; + // из первого уровня также можно брать NumberPosition - отступ,если будет надо; он в пунктах, поэтому тоже может потребоваться пересчёт! + Если СтрРазделить(рПредставлениеПункта, ".", Ложь).Найти(рФорматСписка.ListValue) = 0 Тогда + Сообщить("Внимание! Нарушение нумерации списка для " + рПредставлениеПункта + "!"); + КонецЕсли; + // фиксируем для дальнейшего вывода + соотПараграфовСписков.Вставить(рПараграфСписка.Range.Start, Новый Структура("Номер,Выравнивание", рПредставлениеПункта, рВыравнивание)); + КонецЕсли; + КонецЦикла; + КонецЦикла; + #КонецОбласти + + // FitTextWidth для диапазонов НЕ используем, в т.ч. для комДокумент.Range() + + т = Новый ТабличныйДокумент; + + #Область ПодготовкаТабДокумента + // устанавливаем ширины рабочих колонок А4 + стлб = 1; + Пока Истина Цикл + т.Область(1, стлб, 1, стлб).ШиринаКолонки = Окр(рСантиметр / 4, 2); + стлб = стлб + 1; + Если т.ШиринаТаблицы > рШиринаСтраницы Тогда + Прервать; + КонецЕсли; + КонецЦикла; + #КонецОбласти + + #Область ВыводОсновныхДанных + стрк = 1; + рПравыйКрайнийСтолбец = т.ШиринаТаблицы; + рИдётТаблица = Ложь; + + Для каждого рПараграф Из комДокумент.Paragraphs Цикл + // к сожалению, рПараграф.ListNumberOriginal использовать ненадёнжно + рДиапазон = рПараграф.Range; + + рТекстДиапазона = рДиапазон.Text; + рНачалоДиапазона = рДиапазон.Start; + рКонецДиапазона = рДиапазон.End; + + #Область ВыводПозицииНумерованногоСписка + // использовать рДиапазон.ListFormat.ListLevelNumber и рДиапазон.ListFormat.ListValue не рекомендуется + рПараграфСписка = соотПараграфовСписков.Получить(рНачалоДиапазона); + Если рПараграфСписка = Неопределено Тогда + рПредставлениеПункта = ""; + рВыравнивание = 0; + Иначе + рПредставлениеПункта = СокрЛП(рПараграфСписка.Номер); + рВыравнивание = рПараграфСписка.Выравнивание; + КонецЕсли; + Если ПустаяСтрока(рПредставлениеПункта) Тогда + // нумерации списка нет + рГраницаОбластиПараграфа = 1; + Иначе // надо выводить № пункта списка + рОбластьНомера = т.Область(стрк, 1, стрк, 4); + рОбластьНомера.Объединить(); + рОбластьНомера.Текст = рПредставлениеПункта; + рОбластьНомера.Шрифт = ПостроитьШрифт(ВыборШрифта(рДиапазон)); // или рДиапазон.ListStyle.Font, если они разные + рОбластьНомера.ГоризонтальноеПоложение = ПолучитьВыравнивание(рВыравнивание); + рОбластьНомера.ВертикальноеПоложение = ВертикальноеПоложение.Верх; // по умолчанию + рГраницаОбластиПараграфа = 5; + КонецЕсли; + #КонецОбласти + + комТаблица = Неопределено; + Для каждого знч Из мКомТаблиц Цикл + Если знч.Начало <= рНачалоДиапазона и рНачалоДиапазона <= знч.Конец + и знч.Начало <= рКонецДиапазона и рКонецДиапазона <= знч.Конец + Тогда // можно было бы рДиапазон.InRange(комТаблица.Range), но оно медленнее + комТаблица = знч.Таблица; Прервать; + КонецЕсли; + КонецЦикла; + + Если комТаблица = Неопределено Тогда + рИдётТаблица = Ложь; + + #Область ВыводОбычногоАбзаца + // для параграфа и Диапазон.ParagraphFormat, при необходимости: + // рПараграф.FirstLineIndent - Возвращает или устанавливает значение в пунктах для первой линии или отступа. + // рПараграф.LeftIndent - Отступ слева в пунктах. + // рПараграф.RightIndent - Отступ справа в пунктах. + // рПараграф.LineSpacing - Междустрочный интервал. + // рПараграф.PageSetup.PageWidth аналогично ширине документа в целом, можно не заморачиваться + + рОбластьПараграфа = т.Область(стрк, рГраницаОбластиПараграфа, стрк, рПравыйКрайнийСтолбец); + рОбластьПараграфа.Объединить(); + рОбластьПараграфа.Текст = рТекстДиапазона; + рОбластьПараграфа.Шрифт = ПостроитьШрифт(ВыборШрифта(рДиапазон)); // а не рПараграф.Style.Font! + рОбластьПараграфа.ГоризонтальноеПоложение = ПолучитьВыравнивание(рПараграф.Alignment); // или лучше рДиапазон.ParagraphFormat.Alignment? + рОбластьПараграфа.ВертикальноеПоложение = ВертикальноеПоложение.Верх; // по умолчанию + рОбластьПараграфа.РазмещениеТекста = ТипРазмещенияТекстаТабличногоДокумента.Переносить; // по умолчанию + #КонецОбласти + + стрк = стрк + 1; + Иначе + Если не рИдётТаблица Тогда // выводим таблицу, а далее пропускаем все входящие в неё диапазоны, и идём до её конца + ВывестиТаблицу(комВорд, комТаблица, т, стрк, рСантиметр); + КонецЕсли; + рИдётТаблица = Истина; + Продолжить; // стрк уже "промотана" до нужной позиции пост-таблицы + КонецЕсли; + + КонецЦикла; + + #КонецОбласти + + ЗакрытьДокумент(комДокумент); // без сохранения + ЗакрытьВорд(комВорд); + + ИсправитьНедопустимыеСимволы(т); + Возврат т; + + Исключение + Ошибка = ОписаниеОшибки(); + Причина = ИнформацияОбОшибке(); + + ЗакрытьДокумент(комДокумент); + ЗакрытьВорд(комВорд); + + ВызватьИсключение("Ошибка конвертации в mxl", КатегорияОшибки.ОшибкаВнешнегоИсточникаДанных, "500", Ошибка, Причина); + КонецПопытки; + + Возврат Неопределено; +КонецФункции + +Функция ПостроитьШрифт(комШрифт) + Возврат Новый Шрифт( + комШрифт.Name, + комШрифт.Size, + комШрифт.Bold, + комШрифт.Italic, + комШрифт.Underline, + комШрифт.StrikeThrough, + комШрифт.Scaling + ); +КонецФункции + +Функция ВыборШрифта(рДиапазон) + Результат = рДиапазон.Font; + Если Результат.Size > 9999 Тогда + Результат = рДиапазон.ListStyle.Font; + КонецЕсли; + + Возврат Результат; +КонецФункции + + +Функция ПостроитьРамкуЯчейки(комРамка, чисОтступ) + Если комРамка.Visible Тогда + чисСтиль = комРамка.LineStyle; + рТолщина = 1; + Если чисСтиль = 1 Тогда + рТипЛинии = ТипЛинииЯчейкиТабличногоДокумента.Сплошная; + // если надо, толщину можно сделать подробнее по комРамка.LineWidth + ИначеЕсли чисСтиль = 2 Тогда + рТипЛинии = ТипЛинииЯчейкиТабличногоДокумента.Точечная; + ИначеЕсли чисСтиль = 5 Тогда + рТипЛинии = ТипЛинииЯчейкиТабличногоДокумента.РедкийПунктир; + ИначеЕсли чисСтиль = 6 Тогда + рТипЛинии = ТипЛинииЯчейкиТабличногоДокумента.ЧастыйПунктир; + ИначеЕсли чисСтиль = 7 Тогда + рТипЛинии = ТипЛинииЯчейкиТабличногоДокумента.Двойная; + Иначе + рТипЛинии = ТипЛинииЯчейкиТабличногоДокумента.БольшойПунктир; + КонецЕсли; + рОтступ = (чисОтступ > 0); // пока так + Возврат Новый Линия(рТипЛинии, рТолщина, рОтступ); + Иначе + Возврат Новый Линия(ТипЛинииЯчейкиТабличногоДокумента.НетЛинии); + КонецЕсли; +КонецФункции + + +Функция ПолучитьВыравнивание(чисВыравнивание) + // wdListLevelAlignCenter - 1 – По центру wdListLevelAlignLeft - 0 – По левому краю wdListLevelAlignRight - 2 – По правому краю + Если чисВыравнивание = 1 Тогда + Возврат ГоризонтальноеПоложение.Центр; + ИначеЕсли чисВыравнивание = 2 Тогда + Возврат ГоризонтальноеПоложение.Право; + ИначеЕсли чисВыравнивание = 3 Тогда + Возврат ГоризонтальноеПоложение.ПоШирине; + Иначе + Возврат ГоризонтальноеПоложение.Лево; + КонецЕсли; +КонецФункции + + +Процедура ВывестиТаблицу(комВорд, комТаблица, табДокумент, текСтрока, рСантиметр = 6.25) + //рСантиметр=6.25; + рСимвол7 = Символ(7); + + квоСтрок = комТаблица.Rows.Count; + квоКолонок = комТаблица.Columns.Count; + + Для стркДок = 1 По квоСтрок Цикл + стлб = 1; + + Для стлбДок = 1 По квоКолонок Цикл + Попытка + комЯчейка = комТаблица.Cell(стркДок, стлбДок); + Исключение + Продолжить; + КонецПопытки; + + квоЯчеекМхл = Окр(комВорд.PointsToCentimeters(комЯчейка.Width * 4), 0, РежимОкругления.Окр15как20); // 1 см. это 4 ячейки мхл + рОбластьЯчейки = табДокумент.Область(текСтрока, стлб, текСтрока, стлб + квоЯчеекМхл - 1); + рОбластьЯчейки.Объединить(); + + Если комЯчейка.FitText или комЯчейка.WordWrap Тогда // пока так + рОбластьЯчейки.РазмещениеТекста = ТипРазмещенияТекстаТабличногоДокумента.Переносить; + Иначе + рОбластьЯчейки.РазмещениеТекста = ТипРазмещенияТекстаТабличногоДокумента.Авто; + КонецЕсли; + + рДиапазонЯчейки = комЯчейка.Range; + // + рТекстДиапазонаЯчейки = СокрЛП(рДиапазонЯчейки.Text); + Если Прав(рТекстДиапазонаЯчейки, 1) = рСимвол7 Тогда + рТекстДиапазонаЯчейки = Лев(рТекстДиапазонаЯчейки, СтрДлина(рТекстДиапазонаЯчейки) - 1); + КонецЕсли; + рОбластьЯчейки.Текст = рТекстДиапазонаЯчейки; + // + рОбластьЯчейки.Шрифт = ПостроитьШрифт(ВыборШрифта(рДиапазонЯчейки)); + + // на практике удобнее оставлять автовысоту, но иногда может понадобиться: + //рОбластьЯчейки.АвтоВысотаСтроки=Ложь; + //рОбластьЯчейки.ВысотаСтроки=рСантиметр*Окр(комВорд.PointsToCentimeters(комЯчейка.Height),0,РежимОкругления.Окр15как20); + + рОбластьЯчейки.ГоризонтальноеПоложение = ПолучитьВыравнивание(рДиапазонЯчейки.ParagraphFormat.Alignment); + // отступ - в пунктах, при необходимости требуется пересчёт! + //Если рОбластьЯчейки.ГоризонтальноеПоложение=ГоризонтальноеПоложение.Лево Тогда + // рОбластьЯчейки.Отступ=комЯчейка.LeftPadding; + //ИначеЕсли рОбластьЯчейки.ГоризонтальноеПоложение=ГоризонтальноеПоложение.Право Тогда + // рОбластьЯчейки.Отступ=комЯчейка.RightPadding; + //КонецЕсли; + + вертВыравнивание = комЯчейка.VerticalAlignment; + Если вертВыравнивание = 1 Тогда + рОбластьЯчейки.ВертикальноеПоложение = ВертикальноеПоложение.Центр; + ИначеЕсли вертВыравнивание = 3 Тогда + рОбластьЯчейки.ВертикальноеПоложение = ВертикальноеПоложение.Низ; + Иначе + рОбластьЯчейки.ВертикальноеПоложение = ВертикальноеПоложение.Верх; + КонецЕсли; + + рОбластьЯчейки.ГраницаСверху = ПостроитьРамкуЯчейки(комЯчейка.Borders(-1), комЯчейка.Borders.DistanceFromTop); + рОбластьЯчейки.ГраницаСлева = ПостроитьРамкуЯчейки(комЯчейка.Borders(-2), комЯчейка.Borders.DistanceFromLeft); + рОбластьЯчейки.ГраницаСнизу = ПостроитьРамкуЯчейки(комЯчейка.Borders(-3), комЯчейка.Borders.DistanceFromBottom); + рОбластьЯчейки.ГраницаСправа = ПостроитьРамкуЯчейки(комЯчейка.Borders(-4), комЯчейка.Borders.DistanceFromRight); + + стлб = стлб + квоЯчеекМхл; + КонецЦикла; + + текСтрока = текСтрока + 1; + КонецЦикла; + +КонецПроцедуры + +Процедура ЗакрытьДокумент(комДокумент) + Если Неопределено = комДокумент Тогда + Возврат; + КонецЕсли; + + Попытка + комДокумент.Close(Ложь); + Исключение + ; + КонецПопытки; + комДокумент = Неопределено; +КонецПроцедуры + +Процедура ЗакрытьВорд(комВорд) + Если Неопределено = комВорд Тогда + Возврат; + КонецЕсли; + + Попытка + комВорд.Quit(0); + Исключение + ; + КонецПопытки; + комВорд = Неопределено; +КонецПроцедуры + +//Строки = СтрРазделить("0,1,2,3,4,5,6,7,8,9", ","); +//Числа = Мап("Результат = Число(Элемент) * _.Множитель", Строки, Новый Структура("Множитель", 2)); +//Часть = Фильтр("Условие = Элемент > 4 * _.Множитель", Числа, Новый Структура("Множитель", 2)); +//Сообщить(СтрСоединить(Часть, ",")); +Функция ВыполнитьФрагмент(Знач Код, Вход, ИмяВход = "Вход", ИмяВыход = "Выход", Инициализировать = Ложь, _ = Неопределено) + Выход = ?(Инициализировать, Вход, Неопределено); + + Если НЕ "Вход" = ИмяВход Тогда + Код = СтрШаблон("%1=Вход;%2", ИмяВход, Код); + КонецЕсли; + Если НЕ "Выход" = ИмяВыход Тогда + Код = СтрШаблон("%1;Выход=%2", Код, ИмяВыход); + КонецЕсли; + + Выполнить(Код); + + Возврат Выход; +КонецФункции +Функция Мап(Код, Коллекция, _ = Неопределено) + Результат = Новый Массив; + + Для Каждого Элемент Из Коллекция Цикл + ЭлементКопия = Элемент; + ЭлементКопия = ОбщегоНазначения.СкопироватьРекурсивно(ЭлементКопия); + ЭлементКопия = ВыполнитьФрагмент(Код, ЭлементКопия, "Элемент", "Результат", Истина, _); + Результат.Добавить(ЭлементКопия); + КонецЦикла; + + Возврат Результат; +КонецФункции +Функция Фильтр(КодУсловия, Коллекция, _ = Неопределено) + Результат = Новый Массив; + + Для Каждого Элемент Из Коллекция Цикл + Условие = ВыполнитьФрагмент(КодУсловия, Элемент, "Элемент", "Условие", , _); + Если Условие Тогда + Результат.Добавить(Элемент); + КонецЕсли; + КонецЦикла; + + Возврат Результат; +КонецФункции +Функция ВыполнитьФрагмент_ДляСвертки(Знач Код, Элемент, Знач Результат, _ = Неопределено) + Выполнить(Код); + Возврат Результат; +КонецФункции +Функция Свернуть(Код, Коллекция, Знач Результат = Неопределено, _ = Неопределено) + Для Каждого Элемент Из Коллекция Цикл + Результат = ВыполнитьФрагмент_ДляСвертки(Код, Элемент, Результат, _); + КонецЦикла; + + Возврат Результат; +КонецФункции + +Функция ВзятьНеБольше(Коллекция, Знач Количество) + Результат = Новый Массив; + Для Каждого ТекСтр Из Коллекция Цикл + Если 1 > Количество Тогда + Прервать; + КонецЕсли; + + Результат.Добавить(ТекСтр); + + Количество = Количество - 1; + КонецЦикла; + Возврат Результат; +КонецФункции +Функция Пропустить(Коллекция, Знач Количество) + Результат = Новый Массив; + Сч = 0; + Для Каждого ТекСтр Из Коллекция Цикл + Если 0 < Количество Тогда + Количество = Количество - 1; + Продолжить; + КонецЕсли; + + Результат.Добавить(ТекСтр); + КонецЦикла; + Возврат Результат; +КонецФункции + +Функция АлфавитСистемСчисления(Нотация=36) + Алфавит = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + ДлинаАлфавита = СтрДлина(Алфавит); + Результат = ""; + Если ДлинаАлфавита = Нотация Тогда + Результат = Алфавит; + ИначеЕсли ДлинаАлфавита > Нотация Тогда + Результат = Лев(Алфавит, Нотация); + Иначе + ВызватьИсключение "Алфавит слишком мал"; + КонецЕсли; + + Возврат Результат; +КонецФункции + +Функция ЧислоВДругуюСистему(Знач Значение = 0, Нотация = 36) + Если Нотация <= 0 Тогда + Возврат ""; + КонецЕсли; + + Значение = Цел(Число(Значение)); + Если Значение <= 0 Тогда + Возврат "0"; + КонецЕсли; + + Алфавит = АлфавитСистемСчисления(Нотация); + Результат = ""; + Пока Значение > 0 Цикл + Результат = Сред(Алфавит, Значение % Нотация + 1, 1) + Результат; + Значение = Цел(Значение / Нотация); + КонецЦикла; + + Возврат Результат; +КонецФункции + +Функция ЧислоИзДругойСистемы(Знач Значение = "0", Нотация = 36) + Если Нотация <= 0 Тогда + Возврат 0; + КонецЕсли; + + Значение = СокрЛП(Значение); + Если Значение = "0" Тогда + Возврат 0; + КонецЕсли; + + Алфавит = АлфавитСистемСчисления(Нотация); + Результат = 0; + Длина = СтрДлина(Значение); + Для Позиция = 1 По Длина Цикл + Множитель = Pow(Нотация, Длина - Позиция); + ТекСимвол = Сред(Значение, Позиция, 1); + ИндексСимвола = СтрНайти(Алфавит, ТекСимвол) - 1; + Результат = Результат + ИндексСимвола * Множитель; + КонецЦикла; + Возврат Окр(Результат); +КонецФункции + +Функция Ох(Знач Стр) + Возврат ЧислоИзДругойСистемы(Стр, 16); +КонецФункции + +Функция Hex(Знач Числ) + Возврат ЧислоВДругуюСистему(Числ, 16); +КонецФункции + +Процедура ЗаменитьТекстВТД(ТД, Текст, Замена) + Область = ТД.НайтиТекст(Текст); + Пока НЕ Неопределено = Область Цикл + Область.Текст = СтрЗаменить(Область.Текст, Текст, Замена); + Область = ТД.НайтиТекст(Текст, Область); + КонецЦикла; +КонецПроцедуры + +Процедура ИсправитьНедопустимыеСимволы(ТабДок) + // список символов из: + // https://ru.wikipedia.org/wiki/%D0%A3%D0%BF%D1%80%D0%B0%D0%B2%D0%BB%D1%8F%D1%8E%D1%89%D0%B8%D0%B5_%D1%81%D0%B8%D0%BC%D0%B2%D0%BE%D0%BB%D1%8B + УпрСимволы_ASCII = "0,1,2,3,4,5,6,7,8,9,0B,0C,0E,0F,10,11,12,13,14,15,16,17,18,19,1A,1B,1C,1D,1E,1F,7F"; + УпрСимволы_ISO = "80,81,82,83,84,85,86,87,88,89,8A,8B,8С,8D,8E,8F,90,91,92,93,94,95,96,97,98,99,9A,9B,9C,9D,9E,9F"; + УпрСимволы_Unicode = "034F,2008,200B,200C,200D,200E,200F,2028,2029,202A,202B,202C,202D,202E,2060,2061,2063,2066,2067,2068,2069,206A,206B,206C,206D,206E,206F," + + "FE00,FE01,FE02,FE03,FE04,FE05,FE06,FE07,FE08,FE09,FE0A,FE0B,FE0C,FE0D,FE0E,FE0F,FEFF,FFF9,FFFA,FFFB,FFFC,FFFD"; + + УпрСимволы = СтрШаблон("%1,%2,%3", УпрСимволы_ASCII, УпрСимволы_ISO, УпрСимволы_Unicode); + УпрСимволы = СтрРазделить(УпрСимволы, ","); + УпрСимволы = Мап("Результат = Ох(Элемент)", УпрСимволы); + УпрСимволы = Мап("Результат = Символ(Элемент)", УпрСимволы); + УпрСимволы = ОбщегоНазначенияКлиентСервер.СвернутьМассив(УпрСимволы); + + Для ТекСимвол_Число = Ох("E0100") По Ох("E01EF") Цикл + УпрСимволы.Добавить(Символ(ТекСимвол_Число)); + КонецЦикла; + + ЗаменитьТекстВТД(ТабДок, Символы.ВТаб, Символы.ПС); + + Для Каждого ТекСимвол_Число Из УпрСимволы Цикл + ЗаменитьТекстВТД(ТабДок, ТекСимвол_Число, ""); + КонецЦикла; + +КонецПроцедуры \ No newline at end of file diff --git a/Word2MXL/Forms/Форма.xml b/Word2MXL/Forms/Форма.xml new file mode 100644 index 0000000..e7d8003 --- /dev/null +++ b/Word2MXL/Forms/Форма.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.14"> + <Form uuid="538a646c-ff09-4d5d-92fc-4b90c2dfbe26"> + <Properties> + <Name>Форма</Name> + <Synonym> + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Форма</v8:content> + </v8:item> + </Synonym> + <Comment/> + <FormType>Managed</FormType> + <IncludeHelpInContents>false</IncludeHelpInContents> + <UsePurposes> + <v8:Value xsi:type="app:ApplicationUsePurpose">PlatformApplication</v8:Value> + <v8:Value xsi:type="app:ApplicationUsePurpose">MobilePlatformApplication</v8:Value> + </UsePurposes> + <ExtendedPresentation/> + </Properties> + </Form> +</MetaDataObject> \ No newline at end of file diff --git a/Word2MXL/Forms/Форма/Ext/Form.xml b/Word2MXL/Forms/Форма/Ext/Form.xml new file mode 100644 index 0000000..8db845b --- /dev/null +++ b/Word2MXL/Forms/Форма/Ext/Form.xml @@ -0,0 +1,149 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Form xmlns="http://v8.1c.ru/8.3/xcf/logform" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:dcscor="http://v8.1c.ru/8.1/data-composition-system/core" xmlns:dcsset="http://v8.1c.ru/8.1/data-composition-system/settings" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.14"> + <AutoCommandBar name="ФормаКоманднаяПанель" id="-1"> + <ChildItems> + <Button name="ФормаКонвертировать" id="13"> + <Type>CommandBarButton</Type> + <DefaultButton>true</DefaultButton> + <CommandName>Form.Command.Конвертировать</CommandName> + <ExtendedTooltip name="ФормаКонвертироватьРасширеннаяПодсказка" id="14"/> + </Button> + </ChildItems> + </AutoCommandBar> + <Events> + <Event name="OnCreateAtServer">ПриСозданииНаСервере</Event> + </Events> + <ChildItems> + <UsualGroup name="ГруппаПрогресс" id="15"> + <Title> + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Группа прогресс</v8:content> + </v8:item> + </Title> + <ToolTip> + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Группа прогресс</v8:content> + </v8:item> + </ToolTip> + <Group>Vertical</Group> + <Behavior>Usual</Behavior> + <Representation>None</Representation> + <ShowTitle>false</ShowTitle> + <ExtendedTooltip name="ГруппаПрогрессРасширеннаяПодсказка" id="16"/> + <ChildItems> + <LabelField name="Состояние" id="17"> + <DataPath>Состояние</DataPath> + <TitleLocation>None</TitleLocation> + <TextColor>web:Indigo</TextColor> + <Font ref="style:NormalTextFont" bold="true" italic="false" underline="false" strikeout="false" kind="StyleItem" scale="150"/> + <ContextMenu name="СостояниеКонтекстноеМеню" id="18"/> + <ExtendedTooltip name="СостояниеРасширеннаяПодсказка" id="19"/> + </LabelField> + <ProgressBarField name="Прогресс" id="20"> + <DataPath>Прогресс</DataPath> + <TitleLocation>None</TitleLocation> + <ContextMenu name="ПрогрессКонтекстноеМеню" id="21"/> + <ExtendedTooltip name="ПрогрессРасширеннаяПодсказка" id="22"/> + </ProgressBarField> + </ChildItems> + </UsualGroup> + <UsualGroup name="ГруппаРезультат" id="7"> + <Group>Vertical</Group> + <Behavior>Usual</Behavior> + <Representation>None</Representation> + <ShowTitle>false</ShowTitle> + <ExtendedTooltip name="ГруппаРезультатРасширеннаяПодсказка" id="8"/> + <ChildItems> + <CommandBar name="Группа2" id="9"> + <CommandSource>Item.ДокументРезультат</CommandSource> + <ExtendedTooltip name="Группа2РасширеннаяПодсказка" id="10"/> + <ChildItems> + <Button name="ДокументРезультатСохранить" id="11"> + <Type>CommandBarButton</Type> + <Representation>PictureAndText</Representation> + <CommandName>Form.Item.ДокументРезультат.StandardCommand.Save</CommandName> + <LocationInCommandBar>InCommandBarAndInAdditionalSubmenu</LocationInCommandBar> + <ExtendedTooltip name="ДокументРезультатСохранитьРасширеннаяПодсказка" id="12"/> + </Button> + </ChildItems> + </CommandBar> + <SpreadSheetDocumentField name="ДокументРезультат" id="4"> + <DataPath>ДокументРезультат</DataPath> + <ShowGrid>true</ShowGrid> + <ShowHeaders>true</ShowHeaders> + <ContextMenu name="ДокументРезультатКонтекстноеМеню" id="5"/> + <ExtendedTooltip name="ДокументРезультатРасширеннаяПодсказка" id="6"/> + </SpreadSheetDocumentField> + </ChildItems> + </UsualGroup> + </ChildItems> + <Attributes> + <Attribute name="Объект" id="1"> + <Type> + <v8:Type>cfg:ExternalDataProcessorObject.Word2MXL</v8:Type> + </Type> + <MainAttribute>true</MainAttribute> + </Attribute> + <Attribute name="ДокументРезультат" id="2"> + <Title> + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Документ результат</v8:content> + </v8:item> + </Title> + <Type> + <v8:Type xmlns:mxl="http://v8.1c.ru/8.2/data/spreadsheet">mxl:SpreadsheetDocument</v8:Type> + </Type> + </Attribute> + <Attribute name="Состояние" id="3"> + <Title> + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Состояние</v8:content> + </v8:item> + </Title> + <Type> + <v8:Type>xs:string</v8:Type> + <v8:StringQualifiers> + <v8:Length>0</v8:Length> + <v8:AllowedLength>Variable</v8:AllowedLength> + </v8:StringQualifiers> + </Type> + </Attribute> + <Attribute name="Прогресс" id="4"> + <Title> + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Прогресс</v8:content> + </v8:item> + </Title> + <Type> + <v8:Type>xs:decimal</v8:Type> + <v8:NumberQualifiers> + <v8:Digits>10</v8:Digits> + <v8:FractionDigits>3</v8:FractionDigits> + <v8:AllowedSign>Nonnegative</v8:AllowedSign> + </v8:NumberQualifiers> + </Type> + </Attribute> + </Attributes> + <Commands> + <Command name="Конвертировать" id="1"> + <Title> + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Конвертировать</v8:content> + </v8:item> + </Title> + <ToolTip> + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Конвертировать</v8:content> + </v8:item> + </ToolTip> + <Action>Конвертировать</Action> + </Command> + </Commands> +</Form> \ No newline at end of file diff --git a/Word2MXL/Forms/Форма/Ext/Form/Module.bsl b/Word2MXL/Forms/Форма/Ext/Form/Module.bsl new file mode 100644 index 0000000..ef0b9bb --- /dev/null +++ b/Word2MXL/Forms/Форма/Ext/Form/Module.bsl @@ -0,0 +1,93 @@ + +&НаКлиенте +Асинх Процедура Конвертировать(Команда) + Диалог = Новый ПараметрыДиалогаПомещенияФайлов; + Диалог.Заголовок = "Выберите документ"; + Диалог.МножественныйВыбор = Ложь; + Диалог.Фильтр = "Документы (*.doc,*.docx,*.rtf)|*.doc;*.docx;*.rtf|Все файлы|*.*"; + + Прогресс = 0; + Элементы.ГруппаПрогресс.Видимость = Истина; + Элементы.Прогресс.Видимость = Истина; + Состояние = "Передача файла"; + Оповещение_ОХодеВыполнения = Новый ОписаниеОповещения("ПомещениеФайла_ОповещенияОХодеВыполнения", ЭтаФорма, Неопределено); + ОписаниеФайла = Ждать ПоместитьФайлНаСерверАсинх(Оповещение_ОХодеВыполнения,,,Диалог, ЭтаФорма.УникальныйИдентификатор); + + Элементы.Прогресс.Видимость = Ложь; + Прогресс = 0; + + Если Неопределено = ОписаниеФайла Тогда + Элементы.ГруппаПрогресс.Видимость = Ложь; + Возврат; + КонецЕсли; + + Состояние = "Конвертация"; + ОбновитьОтображениеДанных(Элементы.Состояние); + КонвертироватьНаСервере(ОписаниеФайла.Адрес, ОписаниеФайла.СсылкаНаФайл.Расширение); + Элементы.ГруппаПрогресс.Видимость = Ложь; + Элементы.ГруппаРезультат.Видимость = Истина; +КонецПроцедуры + +&НаКлиенте +Процедура ПомещениеФайла_ОповещенияОХодеВыполнения(ПомещаемыйФайл, Помещено, ОтказОтПомещенияФайла, ДополнительныеПараметры) Экспорт + Прогресс = Помещено; +КонецПроцедуры + +&НаКлиентеНаСервереБезКонтекста +Процедура ПопыткаУдалитьФайлы(Файлы) + Если Неопределено = Файлы Тогда + Возврат; + КонецЕсли; + + Попытка + УдалитьФайлы(Файлы); + Исключение + КонецПопытки; + + Файлы = Неопределено; +КонецПроцедуры + +&НаСервере +Процедура КонвертироватьНаСервере(Знач Адрес, Знач Расширение) + Обработка = РеквизитФормыВЗначение("Объект"); + + РезультатКонвертации = Неопределено; + + ВремФайл = ПолучитьИмяВременногоФайла(Расширение); + Данные = ПолучитьИзВременногоХранилища(Адрес); + Данные.Записать(ВремФайл); + Данные = Неопределено; + ИмяФайла = ВремФайл; + + Попытка + РезультатКонвертации = Обработка.ВывестиДокументВордВМоксель(ИмяФайла); + Исключение + Ошибка = ОписаниеОшибки(); + Причина = ИнформацияОбОшибке(); + + ПопыткаУдалитьФайлы(ВремФайл); + Если ЭтоАдресВременногоХранилища(Адрес) Тогда + УдалитьИзВременногоХранилища(Адрес); + Адрес = Неопределено; + КонецЕсли; + + ВызватьИсключение ("Ошибка конвертации в mxl",КатегорияОшибки.ОшибкаВнешнегоИсточникаДанных,"500",Ошибка,Причина); + КонецПопытки; + + ПопыткаУдалитьФайлы(ВремФайл); + Если ЭтоАдресВременногоХранилища(Адрес) Тогда + УдалитьИзВременногоХранилища(Адрес); + Адрес = Неопределено; + КонецЕсли; + + Если Не Неопределено = РезультатКонвертации Тогда + ДокументРезультат = РезультатКонвертации; + КонецЕсли; + +КонецПроцедуры + +&НаСервере +Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка) + Элементы.ГруппаПрогресс.Видимость = Ложь; + Элементы.ГруппаРезультат.Видимость = Ложь; +КонецПроцедуры