Очень часто менеджеры дублируют информацию в справочниках и время от времени их приходится чистить.
Но как удалить только те элементы справочника, которые не используются в документах?
Следующий пример кода поможет это сделать(в примере обрабатывается 4 справочника: Сотрудники, ФизЛица, Договора и Контрагенты) Скачать: Обработка для УТ 10 :
Код 1C v 8.х сп=Новый СписокЗначений;
сп.Добавить("СотрудникиОрганизаций");
сп.Добавить("ФизическиеЛица");
сп.Добавить("ДоговорыКонтрагентов");
сп.Добавить("Контрагенты");
Для Каждого стр из сп Цикл
текСпр=стр.Значение;
Запрос = Новый Запрос;
Текст =
"ВЫБРАТЬ
| СотрудникиОрганизаций.Ссылка
|ИЗ
| Справочник.%текСпр% КАК СотрудникиОрганизаций
|ГДЕ
| НЕ СотрудникиОрганизаций.ПометкаУдаления И НЕ СотрудникиОрганизаций.ЭтоГруппа";
Запрос.Текст = СтрЗаменить(Текст,"%текСпр%",текСпр);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
итЗаписей = Строка(ВыборкаДетальныеЗаписи.Количество());
ном=0;
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
ном=ном+1; Состояние(текСпр+": "+Строка(ном)+" из "+итЗаписей);
СсылкаНаУдаляемыйЭлемент = ВыборкаДетальныеЗаписи.Ссылка;
// Найти ссылки на удаляемый элемент - СсылкаНаУдаляемыйЭлемент.
МассивСсылок = Новый Массив;
МассивСсылок.Добавить(СсылкаНаУдаляемыйЭлемент);
НайденныеСсылки = НайтиПоСсылкам(МассивСсылок);
Если НайденныеСсылки.Количество() > 0 Тогда
Сообщить("Нельзя удалять элемент:"+Строка(СсылкаНаУдаляемыйЭлемент)+", на него имеются ссылки",СтатусСообщения.Внимание);
Иначе
Сообщить("Удаляем элемент:"+Строка(СсылкаНаУдаляемыйЭлемент),СтатусСообщения.Информация);
// Получаем объект
УдаляемыйЭлемент = СсылкаНаУдаляемыйЭлемент.ПолучитьОбъект();
// Установить пометку
//УдаляемыйЭлемент.УстановитьПометкуУдаления(Истина);
// Удалить сразу
УдаляемыйЭлемент.Удалить();
КонецЕсли;
КонецЦикла;
КонецЦикла;
Недавно, мой постоянный клиент решил проводить маркетинговые исследования по изменению цен на товары у конкурентов... и эти данные захотел использовать в 1С в связке с его прайс-листом + куча отчетов с графиками и процентным отклонением от цен основного конкурента
В результате этого, была написана обработка собирающая данные со страниц разных сайтов. Из целей конфиденциальности - сайты раскрывать не буду...
Вид обработки загрузки данных с сайта в 1С
Ниже код загрузки данных со страницы сайта , смысл такой :
в функция передается адрес страницы сайта полученный текст страницы обрабатывается , удаляются теги из полученного текста формируется ТЗ с данными По названию ищется поставщик из вспомогательного справочника Справочники.Pr_Поставщики.НайтиПоНаименованию(, если нет - создается на выходе ТЗ с данными Код 1C v 8.х Функция ПолучитьТаблицуДанных(Строка)
тзДанных = Новый ТаблицаЗначений;
Сервер = "site.ru";
Соединение = Новый HTTPСоединение(Сервер);
Заголовки = Новый Соответствие;
Заголовки.Вставить("host", Сервер);
ТекАдрес = СтрЗаменить(Строка.Наименование.УРЛСтраницы,"http://","");
ТекАдрес = СтрЗаменить(ТекАдрес,Сервер,"");
Запрос = Новый HTTPЗапрос(ТекАдрес, Заголовки);
Ответ =Соединение.Получить(Запрос);
Если Ответ.КодСостояния = 200 Тогда // Данные получены, обрабатываем их
Содержимое= Ответ.ПолучитьТелоКакСтроку();
//Выведем тест полученной страницы
НачалоБлока = "<table id=" + """" + "table-price" + """" + " cellspacing=" + """" + "0" + """" + " border=" + """" + "1" + """" + " bordercolor=" + """" + "#dedede" + """" + " class=" + """" + "tablesorter" + """" + " >";
//НачалоБлока = "<div class=" + """" + "w100fl" + """" + " id=" + """" + "kurs" + """" + ">";
КонецБлока = "</table>";
ТекстБлока = Сред(Содержимое, Найти(Содержимое, НачалоБлока) + СтрДлина(НачалоБлока), Найти(Содержимое, КонецБлока) - Найти(Содержимое, НачалоБлока) - СтрДлина(НачалоБлока));
//Обработаем тест
обрТекст = СтрЗаменить(ТекстБлока,"<tr>","");
обрТекст = СтрЗаменить(обрТекст,"</tr>",Символы.ПС);
обрТекст = СтрЗаменить(обрТекст," >", ">");
обрТекст = СтрЗаменить(обрТекст,"</th> <th>", " | ");
обрТекст = СтрЗаменить(обрТекст,"</td> <td>", " | ");
обрТекст = СтрЗаменить(обрТекст,"</th> <th class=" + """" + "sortable_header" + """" + ">", " | ");
обрТекст = СтрЗаменить(обрТекст,"</th> <th >", " | ");
обрТекст = СтрЗаменить(обрТекст,"</th><th>", " | ");
обрТекст = СтрЗаменить(обрТекст,"</td><td>", " | ");
обрТекст = СтрЗаменить(обрТекст," >", ">");
RegExp = Новый COMОбъект("VBScript.RegExp");
RegExp.IgnoreCase = Ложь;
RegExp.Global = Истина;
RegExp.MultiLine = Истина;
RegExp.Pattern = "<[^>]*>"; //Ищем теги HTML
обрТекст=RegExp.Replace(обрТекст, "");
//Сообщить(обрТекст);
Если СокрЛП(обрТекст) = "Ни одной позиции не найдено." Тогда
Сообщить(Строка(Строка.Наименование)+ " = Ни одной позиции не найдено! Строка " + Строка.Наименование);
Возврат тзДанных;
КонецЕсли;
Если Найти(обрТекст, "Страница не найдена") > 0 Тогда
Сообщить(Строка(ТекАдрес)+" = Страница не найдена, строка " + Строка.Наименование);
Возврат тзДанных;
КонецЕсли;
//Преобразуем полученный текст в таблицу
Для н=1 По СтрЧислоСтрок(обрТекст)Цикл
СтрТекста=СтрПолучитьСтроку(обрТекст,н);
Если Найти(СтрТекста, "Длина Цена") > 0 Тогда
СтрТекста = СтрЗаменить(СтрТекста, "Длина Цена", "Длина | Цена");
КонецЕсли;
Если Найти(СтрТекста, "Марка стали Цена") > 0 Тогда
СтрТекста = СтрЗаменить(СтрТекста, "Марка стали Цена", "Марка стали | Цена");
КонецЕсли;
Если Найти(СтрТекста, ", Поставщик") > 0 Тогда
СтрТекста = СтрЗаменить(СтрТекста, ", Поставщик", " | Поставщик");
КонецЕсли;
//Выводим текст страницы построчно
мсДанных = ПолучитьМассивИзСтрокиСРазделителем(СтрТекста, "|", Истина);
Если н=1 Тогда
Для Каждого ткЗнач из мсДанных Цикл
СтрЗапрещСимволов = " .,<>""\/-";
ИмяКолонки = ткЗнач;
Для сч33 = 1 по СтрДлина(СтрЗапрещСимволов) Цикл
ЗапрещСимв = Сред(СтрЗапрещСимволов, сч33, 1);
ИмяКолонки = СтрЗаменить(ИмяКолонки, ЗапрещСимв, "_");
КонецЦикла;
// добавим нужное количество колонок- если перед колонкой Поставщик не хватает
// бывает, что в шапке определяется меньше колонок, чем реально в таблице
Если НРег(ИмяКолонки) = "поставщик" Тогда
Для Сч_дк = (Строка.Наименование.Родитель.Поставшик - 2) по тзДанных.Колонки.Количество() Цикл
тзДанных.Колонки.Добавить("Колонка_" + (тзДанных.Колонки.Количество() + 1));
КонецЦикла;
КонецЕсли;
тзДанных.Колонки.Добавить(ИмяКолонки);
КонецЦикла;
тзДанных.Колонки.Добавить("ном", , , 7);
Иначе
НовСтр = тзДанных.Добавить(); нмас=0;
Для Каждого ткЗнач из мсДанных Цикл
НовСтр[нмас] = ткЗнач;
нмас=нмас+1;
КонецЦикла;
НовСтр.ном = н;
КонецЕсли;
//Сообщить(стр);
КонецЦикла;
тзДанных.Колонки.Добавить("ЕстьСоответствие", Новый ОписаниеТипов("Булево"));
тзДанных.Колонки.Добавить("СпрPr_Поставщики", Новый ОписаниеТипов("СправочникСсылка.Pr_Поставщики"));
Для каждого стр из тзДанных Цикл
текПоставщик = Справочники.Pr_Поставщики.НайтиПоНаименованию(стр[Строка.Наименование.родитель.Поставшик-1]);
Если текПоставщик = Справочники.Pr_Поставщики.ПустаяСсылка() Тогда
НовЭлем = Справочники.Pr_Поставщики.СоздатьЭлемент();
НовЭлем.Наименование = СокрЛП(стр[Строка.Наименование.родитель.Поставшик-1]);
НовЭлем.Записать();
текПоставщик = НовЭлем.Ссылка;
КонецЕсли;
стр.СпрPr_Поставщики = текПоставщик;
КонецЦикла;
Иначе
тзДанных.Колонки.Добавить("ЕстьСоответствие", Новый ОписаниеТипов("Булево"));
тзДанных.Колонки.Добавить("СпрPr_Поставщики", Новый ОписаниеТипов("СправочникСсылка.Pr_Поставщики"));
Сообщить("Ошибка получения данных для строки " + Строка.Наименование);
КонецЕсли;
Возврат тзДанных;
КонецФункции
В коде используется вспомогательная функция ПолучитьМассивИзСтрокиСРазделителем
Код 1C v 8.2 УП // Функция разбивает строку разделителем.
//
// Параметры:
// пСтрока - Строка - которую разбиваем;
// *пРазделитель - Строка, "." - символ-разделитель;
// *ОбрезатьНепечатныеСимволы - Булево, *Ложь.
//
// Возвращаемое значение:
// Массив - фрагментов.
//
Функция ПолучитьМассивИзСтрокиСРазделителем(Знач Стр, Разделитель = ".", ОбрезатьНепечатныеСимволы = Ложь) Экспорт
МассивСтрок = Новый Массив;
Если Разделитель = " " Тогда
Стр = СокрЛП(Стр);
Пока 1=1 Цикл
Поз = Найти(Стр,Разделитель);
Если Поз=0 Тогда
МассивСтрок.Добавить(Стр);
Возврат МассивСтрок;
КонецЕсли;
МассивСтрок.Добавить(Лев(Стр,Поз-1));
Стр = СокрЛ(Сред(Стр,Поз));
КонецЦикла;
Иначе
ДлинаРазделителя = СтрДлина(Разделитель);
Пока 1=1 Цикл
Поз = Найти(Стр,Разделитель);
Если Поз=0 Тогда
Фрагмент = Стр;
Если ОбрезатьНепечатныеСимволы Тогда
Фрагмент = СокрЛП(Фрагмент);
КонецЕсли;
МассивСтрок.Добавить(Фрагмент);
Возврат МассивСтрок;
КонецЕсли;
Фрагмент = Лев(Стр,Поз-1);
Если ОбрезатьНепечатныеСимволы Тогда
Фрагмент = СокрЛП(Фрагмент);
КонецЕсли;
МассивСтрок.Добавить(Фрагмент);
Стр = Сред(Стр,Поз+ДлинаРазделителя);
КонецЦикла;
КонецЕсли;
Возврат МассивСтрок;
КонецФункции // ПолучитьМассивИзСтрокиСРазделителем()
Конечно, перед тем как мы начали это делать - прошерстили интернет и нашли несколько решений , вот они:
Код 1C v 8.х Соединение = ПолучитьCOMОбъект("","Microsoft.XMLHTTP");
ИмяВременногоФайла=ПолучитьИмяВременногоФайла("htm");
Соединение.open("GET", "http://mamba.ru/my", 0);
Соединение.send();
//status: //404 - Not Found //200 - Ok
ТаймАут = 200;
Начало=ТекущаяДата();
Пока Соединение.readyState <> 4 И (ТаймАут=0 ИЛИ ТекущаяДата()-Начало<ТаймАут) Цикл
бфДиалоги.ксОбработкаПрерыванияПользователя();
КонецЦикла;
//Сохраняем во временный файл
обСохранитьДвоичныйБуферВФайл(Соединение.responseBody, ИмяВременногоФайла);
Соединение.open("POST", "http://mamba.ru/my");
Соединение.send("login=xxx&password=&&&");
Функция обСохранитьДвоичныйБуферВФайл(Буфер, ИмяФайла) Экспорт
Поток = Новый COMОбъект("ADODB.Stream");
Поток.Type = 1; //Бинарный
Поток.Mode = 3;
Поток.Open();
Поток.Write(Буфер);
Поток.SaveToFile(ИмяФайла);
Поток.Close();
КонецФункции
Код 1C v 8.х НТТР = ПолучитьCOMОбъект("","Microsoft.XMLHTTP");
ИмяФайлаОтвета = КаталогВременныхФайлов() + "filename.tmp";
НТТР.open("GET", "www.google.com",0,,);
НТТР.send();
StreamTypeEnum = Новый Структура("adTypeBinary, adTypeText", 1, 2);
ConnectModeEnum = Новый Структура(
"adModeRead, adModeReadWrite, adModeRecursive, adModeShareDenyNone,
|adModeShareDenyRead, adModeShareDenyWrite, adModeShareExclusive,
|adModeUnknown, adModeWrite", 1, 3, 4194304, 16, 4, 8, 12, 0, 2);
SaveOptionsEnum = Новый Структура("adSaveCreateNotExist, adSaveCreateOverWrite", 1, 2);
StreamOut = Новый COMОбъект("ADODB.Stream");
StreamOut.Type = StreamTypeEnum.adTypeBinary;
StreamOut.Mode = ConnectModeEnum.adModeReadWrite; //Нужны и чтение и запись
StreamOut.Open(); //Открыли на чтение и запись
StreamOut.Write(НТТР.responseBody);
StreamOut.SaveToFile(ИмяФайлаОтвета, SaveOptionsEnum.adSaveCreateOverWrite); //"2" - перезапись файла
StreamOut.Close();
И даже не этом сайте есть статья : Парсер сайта связного на 1С
Нужен парсер сайта в 1С!? - Обращайтесь, контакты в
профиле Для одной организации надо было реализовать документы, где вместо табличной части надо использовать дерево и все это на управляемых формах. Но дерево нельзя сохранить в базе в текущем виде. Пришлось использовать табличную часть документа для хранения данных дерева. И при открытии формы получать данные из ТЧ и выводить их в дерево. Далее все манипуляции производить с деревом и при сохранении документа помещать данные в обратно в ТЧ.
Поиск по интернету не дал нужного варианта, пришлось реализовавыть свой механизм, используя информацию которая была на просторах интернета.
Для реализации такого механизма в ТЧ был добавлен реквизит “КлючСвязи” (обязательный реквизит) с типом число, куда помещался “НомерСтроки” (стандартный реквизит ТЧ) родителя (верхний уровень). А самый верхний элемент дерева имеет “КлючСвязи” равный 0.
На картинке ниже видно структуру дерева и структуру ТЧ
Нагрузка на сервер осуществляется при окрытии и при сохранении документа. А с деревом работают уже на клиенте.
На рабочей базе обрабатывается около 200 строк в одном документе.
Открытие и сохранение документа происходит моментально. С большем количеством строк не тестировалось.
Чтобы алгорит правильно работал, у рекизита фомы с типом дерево значений должны быть все реквизиты табличной части, кроме “КлючСвязи” и “НомерСтроки”. Иначе платформа выдаст ошибку. В дерево можо добавлять свои реквизиты отличные от ТЧ, они будут использоваться только в дереве.
Ниже приведен код преобразования дерева в таблицу и обратно .
Код 1C v 8.2 УП &НаКлиенте
Процедура КомандаТаблицуВДерево(Команда)
КомандаТаблицуВДеревоНаСервере();
КонецПроцедуры
&НаСервере
Процедура КомандаТаблицуВДеревоНаСервере()
Дерево = ТаблицаВДерево(РеквизитФормыВЗначение("Объект"), "Товары");//Товары - имя табличной части
ЗначениеВРеквизитФормы(Дерево, "ДеревоЗначений");//ДеревоЗначений - реквизит формы с типом дерево значений
Элементы.ДеревоЗначений.Обновить();
КонецПроцедуры
&НаКлиенте
Процедура КомандаДеревоВТаблицу(Команда)
КомандаДеревоВТаблицуНаСервере();
КонецПроцедуры
&НаСервере
Процедура КомандаДеревоВТаблицуНаСервере()
Объект.Товары.Очистить();
ДОбъект = РеквизитФормыВЗначение("Объект");
ДеревоВТаблицу(ДОбъект, РеквизитФормыВЗначение("ДеревоЗначений"), "Товары");
ЗначениеВРеквизитФормы(ДОбъект, "Объект");
КонецПроцедуры
Формирование дерева из таблицы значений
Код 1C v 8.2 УП //ФОРМИРОВАНИЕ ДЕРЕВА ИЗ ТАБЛИЦЫ
&НаСервере
Функция ТаблицаВДерево(ДокОбъект, НаименованиеТабличнойЧастиДокумента, КлючСвязи = NULL, ЭлементРодитель = NULL) Экспорт
//ПОДГОТОВКА КОЛОНОК ДЕРЕВА
КолонкиТаблицы = ДокОбъект.Метаданные().ТабличныеЧасти[НаименованиеТабличнойЧастиДокумента].Реквизиты;
ДеревоЗначений2 = Новый ДеревоЗначений;
Для каждого Кол из КолонкиТаблицы Цикл
Если Кол.Имя = "НомерСтроки" ИЛИ Кол.Имя = "КлючСвязи" Тогда
Продолжить;
Иначе
ДеревоЗначений2.Колонки.Добавить(Кол.Имя, Новый ОписаниеТипов(Кол.Тип));
КонецЕсли;
КонецЦикла;//ДеревоЗначений.Строки.Очистить();
Если КлючСвязи = NULL И ЭлементРодитель = NULL Тогда
//ПЕРВЫЙ ВЫЗОВ ПРОЦЕДУРЫ (КОРНЕВЫЕ ЭЛЕМЕНТЫ)
ИсточникВыборки = ДеревоЗначений2.Строки;
КлючСвязи = 0; // ЭЛЕМЕНТ ВЕРХНЕГО УРОВНЯ ИМЕЕТ НОМЕР СТРОКИ РОДИТЕЛЯ 0 (ОБЯЗАТЕЛЬНЫЙ РЕКВИЗИТ)
Иначе
//ВНУТРЕННИЙ ВЫЗОВ ПРОЦЕДУРЫ (ПОДЧИНЕННЫЕ ЭЛЕМЕНТЫ)
ИсточникВыборки = ЭлементРодитель.Строки;
КонецЕсли;
Фильтр = Новый Структура("КлючСвязи", КлючСвязи);
М = ДокОбъект[НаименованиеТабличнойЧастиДокумента].НайтиСтроки(Фильтр);
Если М.Количество() = 0 Тогда
Возврат ДеревоЗначений2;
КонецЕсли;
Для каждого Стр из М Цикл
Элемент = ИсточникВыборки.Добавить();
Для каждого Кол из КолонкиТаблицы Цикл
Если Кол.Имя = "НомерСтроки" ИЛИ Кол.Имя = "КлючСвязи" Тогда
Продолжить;
Иначе
Элемент[Кол.Имя] = Стр[Кол.Имя];
КонецЕсли;
КонецЦикла;
ТаблицаВДерево(ДокОбъект, НаименованиеТабличнойЧастиДокумента, Стр.НомерСтроки, Элемент); //ДОБАВЛЕНИЕ ПОДЧИНЁННЫХ ЭЛЕМЕНТОВ В ДЕРЕВО
КонецЦикла;
Возврат ДеревоЗначений2;
КонецФункции
Формирование таблицы из дерева
Код 1C v 8.2 УП //ФОРМИРОВАНИЕ ТАБЛИЦЫ ИЗ ДЕРЕВА
&НаСервере
Процедура ДеревоВТаблицу(ДокОбъект, ДеревоЗначений, НаименованиеТабличнойЧастиДокумента, СтрокаДерева = NULL, КлючСвязи = NULL) Экспорт
Если СтрокаДерева = NULL И КлючСвязи = NULL Тогда
//ПЕРВЫЙ ВЫЗОВ ПРОЦЕДУРЫ (КОРНЕВЫЕ ЭЛЕМЕНТЫ)
ПервыйВызов = Истина;
ДокОбъект[НаименованиеТабличнойЧастиДокумента].Очистить();
ИсточникВыборки = ДеревоЗначений.Строки;
КлючСвязи = 0; // ЭЛЕМЕНТ ВЕРХНЕГО УРОВНЯ ИМЕЕТ НОМЕР СТРОКИ РОДИТЕЛЯ 0 (ОБЯЗАТЕЛЬНЫЙ РЕКВИЗИТ)
Иначе
//ВНУТРЕННИЙ ВЫЗОВ ПРОЦЕДУРЫ (ПОДЧИНЕННЫЕ ЭЛЕМЕНТЫ)
ПервыйВызов = Ложь;
ИсточникВыборки = СтрокаДерева.Строки;
КонецЕсли;
Для каждого Стр из ИсточникВыборки Цикл
НС = ДокОбъект[НаименованиеТабличнойЧастиДокумента].Добавить();
Для каждого Кол из ДокОбъект.Метаданные().ТабличныеЧасти[НаименованиеТабличнойЧастиДокумента].Реквизиты Цикл
Если Кол.Имя = "КлючСвязи" Тогда
НС.КлючСвязи = КлючСвязи
ИначеЕсли Кол.Имя = "НомерСтроки" Тогда
Продолжить;
Иначе
НС[Кол.Имя] = Стр[Кол.Имя];
КонецЕсли;
КонецЦикла;
Если НЕ Стр.Строки.Количество() = 0 Тогда
ДеревоВТаблицу(ДокОбъект,,НаименованиеТабличнойЧастиДокумента, Стр, НС.НомерСтроки);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Конвертация таблиц из Excel в MXL - скачать Converter Excel v MXL:
Для 8.х -
Скачивать файлы может только зарегистрированный пользователь!
Для 7.7 -
Скачивать файлы может только зарегистрированный пользователь!
Код 1C v 8.х // Выбор файла Microsoft Excel
Procedure FileNameStartChoice(Element, StdProcessing)
StdProcessing = False;
DialogFile = New FileDialog(FileDialogMode.Open);
DialogFile.Filter = "Файлы Microsoft Excel (*.xls)|*.xls";
DialogFile.DefaultExt = "xls";
If DialogFile.Choose() Then
FileName = DialogFile.FullFileName;
EndIf;
EndProcedure // FileNameStartChoice()
// Получить список листов текущей книги
Function GetSheets(ExcelApplication)
ListS_electSheet = New ValueList;
ListS_electSheet.Add(0, "Все листы");
NumberSheet = 0;
For FirstSheet = 1 To ExcelApplication.Worksheets.Count Do
NumberSheet = NumberSheet + 1;
ListS_electSheet.Add(
NumberSheet, ExcelApplication.WorkSheets(NumberSheet).Name
);
EndDo;
Return ListS_electSheet;
EndFunction // GetSheets()
// Преобразование XLS в MXL
Procedure ButtonExecuteClick()
If IsBlankString(FileName) Then
DoMessageBox("Не указано имя файла");
Return;
EndIf;
Try
ExcelApplication = GetCOMObject(FileName); // Excel.Application
Except
DoMessageBox("Ошибка чтения файла: " + FileName + " возможно защищен паролем.");
Return;
EndTry;
S_electSheet = 0;
S_electSheet = GetSheets(ExcelApplication).ChooseItem("Выберите лист", S_electSheet);
If S_electSheet = Undefined Then
Return;
EndIf;
S_electNumberSheet1 = S_electSheet.Value;
S_electNumberSheet2 = S_electNumberSheet1;
If S_electNumberSheet1 = 0 Then
S_electNumberSheet1 = 1;
S_electNumberSheet2 = ExcelApplication.Worksheets.Count
EndIf;
frmProgressBar = GetForm("FormProgressBar");
frmProgressBar.Caption = "Обрабатывается файл: " + FileName;
frmProgressBar.Controls.ProgressBarAll.MaxValue = S_electNumberSheet2;
frmProgressBar.Controls.ProgressBarAll.Value = 0;
For NumberSheet = S_electNumberSheet1 To S_electNumberSheet2 Do
frmProgressBar.Open();
SprDoc = New SpreadsheetDocument;
Try
WorkSheet = ExcelApplication.Sheets(NumberSheet).UsedRange;
Except
DoMessageBox(ErrorDescription());
Return;
EndTry;
AllStrings = WorkSheet.Rows.Count; // Всего строк
AllColumns = WorkSheet.Columns.Count; // Всего колонок
AllCells = AllStrings * AllColumns; // Все ячейки
frmProgressBar.Controls.InfoProgressBarAll.Value = "Обрабатывается лист № " +
NumberSheet + " из " +
S_electNumberSheet2;
frmProgressBar.Controls.ProgressBarAll.Value = frmProgressBar.Controls.ProgressBarAll.Value + 1;
If AllCells < 2 Then
Continue; // Пустой лист
EndIf;
frmProgressBar.Controls.ProgressBarCur.MaxValue = AllStrings;
frmProgressBar.Controls.ProgressBarCur.Value = 0;
For CurrentString = 1 To AllStrings Do
For CurrentColumn = 1 To AllColumns Do
frmProgressBar.Controls.InfoProgressBarCur.Value = "Обрабатывается строка №: " +
TrimAll(CurrentString) +
" из " + AllStrings +
", колонка №: " +
TrimAll(CurrentColumn) +
" из " + AllColumns;
Try
CurrentCell = WorkSheet.Cells(
CurrentString,
CurrentColumn
);
SlcCell = SprDoc.Area(
CurrentString,
CurrentColumn,
CurrentString,
CurrentColumn
);
SlcCell.RowHeight = CurrentCell.RowHeight;
SlcCell.ColumnWidth = CurrentCell.ColumnWidth;
// Горизонтальное положение
SlcCell.HorizontalAlign = mListHorizontalAlign.Get(
Format(CurrentCell.HorizontalAlignment, "NG=0")
);
// Вертикальное положение
SlcCell.VerticalAlign = mListVerticalAlign.Get(
Format(CurrentCell.VerticalAlignment, "NG=0")
);
// Размещение текста
SlcCell.TextPlacement = ?(
CurrentCell.WrapText = 0,
SpreadsheetDocumentTextPlacementType.Auto,
SpreadsheetDocumentTextPlacementType.Wrap
);
FontCell = CurrentCell.Font;
// Цвет фона
SlcCell.BackColor = mColorRGB(
CurrentCell.Interior.Color
);
// Цвет текста
SlcCell.TextColor = mColorRGB(
FontCell.Color
);
SlcCell.Font = New Font(
FontCell.Name,
Number(FontCell.Size),
?(Number(FontCell.Bold) = 0,
False, True),
?(Number(FontCell.Italic) = 0,
False, True),
?(Format(Number(FontCell.Underline),"NG=0") = "-4142",
False, True),
?(FontCell.Strikethrough, // Зачеркнутый шрифт
True, False)
);
SlcCell.Text = CurrentCell.Value;
// Рамка
Try
SlcCell.LeftBorder = mStyleBorder(CurrentCell, 7);
SlcCell.TopBorder = mStyleBorder(CurrentCell, 8);
SlcCell.RightBorder = mStyleBorder(CurrentCell, 10);
SlcCell.BottomBorder = mStyleBorder(CurrentCell, 9);
Except
EndTry;
SlcCell.Details = CurrentCell.Formula;
// Объединение ячеек
If (CurrentCell.MergeCells <> 0) and
(Find(CurrentCell.MergeArea.Rows.Address(,, 2),
CurrentCell.Address(,, 2)) = 1) Then
SlcCell = SprDoc.Area(
CurrentString,
CurrentColumn,
(CurrentString + CurrentCell.MergeArea.Rows.Count - 1),
(CurrentColumn + CurrentCell.MergeArea.Columns.Count - 1)
);
SlcCell.Merge();
EndIf;
Except
Message(ErrorDescription());
EndTry;
EndDo;
frmProgressBar.Controls.ProgressBarCur.Value = frmProgressBar.Controls.ProgressBarCur.Value + 1;
UserInterruptProcessing(); // Прерывание пользователя Ctrl+Break
EndDo;
SprDoc.Show("" + TrimAll(FileName) + ", лист " + NumberSheet,"");
EndDo;
frmProgressBar.Close();
ExcelApplication = "";
EndProcedure // ButtonExecuteClick()
Шаблон
Функции возвращают строковое значение, сформированное в соответствии с заданным параметром <Строка_шаблон>, заменив в ней все встроенные выражения, заключенные в квадратные скобки, на их строковые значения.
Строковое значение параметра <Строка_шаблон>
обрабатывается следующим образом: символы "[" , "]" (квадратные скобки) являются специальными символами, которые выделяют поля, содержащие встроенные выражения. Выделенные поля фиксируют свою длину с учетом ограничивающих скобок. Например:
Имя Клиента [Имя], телефон: [Телефон]
После встроенного выражения может стоять символ "#", после которого следует Форматная_строка описанная в функции Формат. В этом случае в данное поле будет проставлен результат выражения, обработанный функцией Формат.
Код 1C v 7.x
Стр = Шаблон("Это название услуги: [Услуга.Наименование]");
// выдает: "Это название услуги: Доставка Товара"
ФиксШаблон
В отличие от функции Шаблон, поля замещаются значениями выражений с сохранением своей длины в символах, то есть обрезаются, если поле короче результата вычисления выражения и дополняются пробелами если длиннее. Если результат числовой, то в границах поля строка прижимается к правой границе.
Код 1C v 7.x
// ниже - пример с дополнением пробелами
Стр = ФиксШаблон("Это название услуги [Услуга.Наименование]");
// выдает: "Это название услуги Доставка Товара"
// далее - с сокращением строки
Стр = ФиксШаблон("Это название услуги [Услуга.Наименование]");
// выдает: "Это название услуги Упаковка товара"
Примеры вспомогательных функций для вычисления выражений с помощью системной функции Шаблон():
Код 1C v 7.x
// Возвращает объект любого типа. По сути является универсальной, но
// работает дольше чем _Вычислить(), поэтому рекомендовал бы
// использовать ее когда нужно вернуть именно объект
Функция _ВычислитьОбъект( Выражение ) Экспорт
Возврат ЗначениеИзСтроки(Шаблон( "[ЗначениеВСтроку("+ Выражение+")]"));
КонецФункции
// Возвращает число. Использую ее когда нужно получить результат выполнения
// лок. функции, которые обычно возвращают 0/1 или когда просто нужно вызвать
// лок. функцию из глоб. модуля
Функция _Вычислить( Выражение) Экспорт
Возврат Число(Шаблон( "["+ Выражение+ "]"));
КонецФункции
Вызов функции осуществляется так:
_Вычислить( "ИмяЛокФункции()");
// Возвращает строку. Функцию удобно использовать когда нужно получить значение
// лок. переменной в гл. модуле
Функция _ВычислитьСтроку( Выражение) Экспорт
Возврат Строка(Шаблон( "["+ Выражение+ "]"));
КонецФункции
Вызов функции осуществляется так:
глПерем= _ВычислитьСтроку( "ЛокПерем");
// Присвоение. Функция используется для присвоения значений локальным переменным из гл. модуля
Функция _Присвоение ( Приемник ,Источник) Экспорт
Попытка
Приемник = Источник ;
Исключение
КонецПопытки;
КонецФункции
Функция вызывается примерно так:
_Вычислить ("_Присвоение(ЛокПерем,глПерем)" );