Имя: Пароль:
1C
1С v8
Создание внешней обработки
,
0 DEaD_EGOR
 
24.03.16
09:36
Народ, Доброго времени суток. Подскажите, создаю с нуля внешнюю обработку. Суть её проста. Пользователь открывает в ней файл Эксель, обработка читает его, на сервере создаёт форму, заполняет её и на клиенте выдаёт пользователю Новый документ Реализация Товаров уже заполненный данными из Экселя. БП 3,0...

Вот собсна весь код

&НаКлиенте
Процедура ИмяФайлаНачалоВыбора(Элемент, СтандартнаяОбработка)
    
    ДиалогВыбора = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
    ДиалогВыбора.Заголовок = "Выберите файл";
        
    Если ДиалогВыбора.Выбрать() Тогда
        Объект.ИмяФайла = ДиалогВыбора.ПолноеИмяФайла;
    Иначе    
         Возврат;
    КонецЕсли;
    
КонецПроцедуры

&НаСервере
Процедура ЗагрузитьФайлНаКлиенте(мФорма)
                
    //подключаемся к эксель
    Попытка
        Excel = Новый COMОбъект("Excel.Application");
        Книга = Excel.WorkBooks.Open(Объект.ИмяФайла);
    Исключение
        Сообщить("Ошибка при открытии файла с помощью Excel! Загрузка не будет произведена!");
        Сообщить(ОписаниеОшибки());
        Возврат;
    КонецПопытки;
        
    Попытка
        //Открываем необходимый лист
        Excel.Sheets(1).Select();  // лист 1, по умолчанию  
    Исключение
        //Закрываем Excel
        Excel.ActiveWorkbook.Close();  
        Excel = 0;
        Сообщить("Файл "+Строка(Объект.ИмяФайла)+" не соответствует необходимому формату! Первый лист не найден!");
        Возврат;
    КонецПопытки;  
                
    //Получим количество строк и колонок.
    //В разных версиях Excel получаются по-разному, поэтому сначала определим версию Excel
    Версия = Лев(Excel.Version,Найти(Excel.Version,".")-1);
    Если Версия = "8" тогда
        ФайлСтрок   = Excel.Cells.CurrentRegion.Rows.Count;
        ФайлКолонок = Макс(Excel.Cells.CurrentRegion.Columns.Count, 13);
    Иначе
        ФайлСтрок   = Excel.Cells(1,1).SpecialCells(11).Row;
        ФайлКолонок = Excel.Cells(1,1).SpecialCells(11).Column;  
    Конецесли;
      
    //// Создание колонок табличного документа
     ТабЗнач = Новый ТаблицаЗначений;
     ТабЗнач.Колонки.Добавить("Номенклатура");
     ТабЗнач.Колонки.Добавить("Количество");
     ТабЗнач.Колонки.Добавить("Цена");
     ТабЗнач.Колонки.Добавить("Ставка");

    //считываем первую строку и генерируем колонки  
    Для НС = 2 по ФайлСтрок Цикл  // НС указываем с какой строки начинать обработку        
            
        НоваяСтрока = ТабЗнач.Добавить();
        НоваяСтрока.Номенклатура = Excel.Cells(НС, 2).Text;
        
        НоваяСтрока.Количество = Excel.Cells(НС, 3).Text;
        
        НоваяСтрока.Цена = Excel.Cells(НС, 4).Text;
        НоваяСтрока.Ставка = Excel.Cells(НС, 6).Text;
                            
    КонецЦикла;  
                
     // Закрыть COM соединение для экономии памяти
     Excel.Application.Quit();
    
     ЗагрузитьПрайсНаСервере(ТабЗнач,мФорма);
    
     //#Если Клиент тогда    
     //КопироватьДанныеФормы(ФормаОбъект,мФорма);
     //мФорма.Модифицированность = Истина;
     //мФОрма.ЦеныИВалюта = "НДС сверху";
     //Мформа.Открыть();
     //МФорма.ЦеныИВалюта = "НДС сверху";
     //#КонецЕсли
                        
КонецПроцедуры

&НаКлиенте
Процедура ЗагрузитьФайл(Команда)
    
     //Создаём формму документа
     мФорма = ПолучитьФорму("Документ.РеализацияТоваровУслуг.Форма.ФормаДокументаТовары");
     ФормаОбъект = мФорма.Объект;                                                                            
    
     ЗагрузитьФайлНаКлиенте(ФормаОбъект);
     КопироватьДанныеФормы(ФормаОбъект, мФорма.Объект);
     мФорма.Открыть();

КонецПроцедуры
    
&НаСервере
Функция ЗагрузитьПрайсНаСервере (Таблица,мФорма);
    
    Для Каждого СТР из Таблица Цикл
        
        Новаястрока = мФорма.Товары.Добавить();
        мНоменклатура = Справочники.Номенклатура.НайтиПоНаименованию(Стр.Номенклатура);
        
        Если мНоменклатура <> Справочники.Номенклатура.ПустаяСсылка() Тогда
            Новаястрока.Номенклатура = мНоменклатура;
        Иначе Новаястрока.Номенклатура = СоздатьНоменклатуруНаСервере(СТР.Номенклатура);
        КонецЕсли;
        
                
    КонецЦикла;
    
КонецФункции

&НаСервере    
Функция СоздатьНоменклатуруНаСервере (Наименование)
    
    
    
КонецФункции


В итоге форма открывается, но не заполняется значениями.. Что я не так делаю, подскажите.. Я-новичок в этом, уже 3 день бьюсь..
1 Ёпрст
 
24.03.16
09:37
сообщения на сервере кому отправляешь ?
2 DEaD_EGOR
 
24.03.16
09:38
(1) в смысле-сообщения на сервере?
3 Timon1405
 
24.03.16
09:38
(1) Глобальный контекст (Global context)
Сообщить (Message)
Доступность:
Тонкий клиент, веб-клиент, сервер, толстый клиент, внешнее соединение.
4 DEaD_EGOR
 
24.03.16
09:41
(1) ААА, ты про процедуру открытия экселя? это мелочи... изначально эт делалось на клиенте.. видимо упустил..
5 mehfk
 
24.03.16
09:45
мФорма = ПолучитьФорму("Документ.РеализацияТоваровУслуг.Форма.ФормаДокументаТовары");
     ФормаОбъект = мФорма.Объект;                                                                            
    
....
     КопироватьДанныеФормы(ФормаОбъект, мФорма.Объект);
     мФорма.Открыть();

Это какой-то шаманизм.
Нужно:
а) создать объект и заполнить его
б) открыть форму, передав в параметры.ключ этот объект
6 DEaD_EGOR
 
24.03.16
09:48
(5) а-на сервере, б - на клиенте... так?
7 DEaD_EGOR
 
24.03.16
09:48
(6) а, нет. форма получаться должна по логике из клиента...
8 DEaD_EGOR
 
24.03.16
10:00
(5) как это сделать, пример хотябы можешь подсказать? я прост гугл перерыл, моего случая там нету((
9 mehfk
 
24.03.16
10:19
Это я из рабочей обработки скопировал :)
&НаКлиенте
Процедура СоздатьПоступление(Команда)
    
    Док = СоздатьПоступлениеНаСервере();
    Если Док <> Неопределено Тогда
    //    ОткрытьФорму("Документ.ПоступлениеТоваровУслуг.ФормаОбъекта", Новый Структура("Ключ", Док));
        ПоказатьЗначение(, Док);
    КонецЕсли;
    
КонецПроцедуры
10 DEaD_EGOR
 
24.03.16
10:25
(9) вообще мне щас необходимо на основании кода из темы пропарсить полученную таблицу и значениями оттуда заполнить форму нового документа...

Для Каждого СТР из Таблица Цикл
        
        НоваяСтрока = мФорма.Товары.Добавить();
        мНоменклатура = Справочники.Номенклатура.НайтиПоНаименованию(Стр.Номенклатура);
Это заполняет номенклатуру. Остаётся заполнить цены, количество и т.д.... вот я нее могу понять, как это сделать?....
11 Defender aka LINN
 
24.03.16
10:32
(0) Рекомендую поразмыслить, что будет, когда сервер начнет искать файл "C:\Файл.xml", который лежит на клиентской машине
12 DEaD_EGOR
 
24.03.16
10:35
(11)Я тестил в отладчике, со своего рабочего стола беру файл и он его открывает....
13 DEaD_EGOR
 
24.03.16
10:42
Ну а всё-таки, как решить вопрос с (10)?
14 Defender aka LINN
 
24.03.16
10:52
(12) А, ну раз так, то конечно, да...
Для развлечения с другой машины запусти. Удивишься.

Ну и - у вас на всех серверах офис установлен? Серьезно?
15 MishaD
 
24.03.16
10:53
(13) ну если у тебя номенклатуру добавляет, то аналогично.
НоваяСтрока.Количество=Стр.Количество
и.т.д
16 Начинающий_13
 
24.03.16
10:56
Сделай так
&НаКлиенте
Процедура ПутьКФайлуНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
    
    
    ДиалогВыбора = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
    ДиалогВыбора.Фильтр =  "Все форматы (*.xls;*.xlsx;*.dbf;*mxl)|*.xls;*.xlsx;*.dbf;*.mxl|"
    + "Формат Excel 2003 (*.xls)|*.xls|"
    + "Формат Excel 2007 (да) 2010 (нет  делать)(*.xlsx)|*.xlsx|"
    + "Формат MXL Делать (*.mxl)|*.mxl|"
    + "Формат DBF (*.dbf)|*.dbf|";

    ДиалогВыбора.Заголовок = "Выберите файл ...";
    ДиалогВыбора.ИндексФильтра               = 0;
    //ДиалогВыбора.ПолноеИмяФайла              = Элемент.Значение;
    ДиалогВыбора.ПолноеИмяФайла              = Объект.ПутьКФайлу;
    ДиалогВыбора.ПроверятьСуществованиеФайла = Ложь;
    ДиалогВыбора.МножественныйВыбор          = Ложь;
    Если ДиалогВыбора.Выбрать() Тогда                                            
        
        //Элемент.Значение = ДиалогВыбора.ПолноеИмяФайла;
        Объект.ПутьКФайлу = ДиалогВыбора.ПолноеИмяФайла;
        ПутьКФайлуПриИзменении(Элемент);
        
        ФайлНаДиске = Новый Файл(ДиалогВыбора.ПолноеИмяФайла);
        Если нРег(ФайлНаДиске.Расширение) = ".xls" Тогда
            ////////ЗагрузкаФайла_Эксель();
            Результат = ЗагрузкаФайла_Эксель();
        ИначеЕсли нРег(ФайлНаДиске.Расширение) = ".xlsx" Тогда
            //ЗагрузкаФайлаЭксель_2007_2010();
        ИначеЕсли нРег(ФайлНаДиске.Расширение) = ".mxl" Тогда
            
        ИначеЕсли нРег(ФайлНаДиске.Расширение) = ".dbf" Тогда
            
        КонецЕсли;
        
    КонецЕсли;
    
КонецПроцедуры

Функция  ЗагрузкаФайла_Эксель()
    
    //Попытка    
    Попытка
        Excel = новый COMОбъект("Excel.Application");
    Исключение
        Сообщить("Похоже, Excel на компьютере не установлен. Необходимо выполнить установку/переустановку Excel.");
        Возврат Ложь;
    КонецПопытки;
    //Тут надо почистить промежуточную табличку
    н=0;
    удалить=0;
    УдаляемыеРеквизиты = Новый Массив();

    Для й=1 по Объект.КолонкиИсточника.Количество() Цикл
        н=н+1;
        ЭлементДляУдаления = Элементы.Найти(СокрЛП("Колонка"+строка(н)));
        Если Не ЭлементДляУдаления = Неопределено Тогда
            УдаляемыеРеквизиты.Добавить(ЭлементДляУдаления.ПутьКДанным);
            Элементы.Удалить(ЭлементДляУдаления);
            Удалить = 1;
        КонецЕсли;    
    КонецЦикла;//Очистить
    Если Удалить =1 Тогда
        ИзменитьРеквизиты(, УдаляемыеРеквизиты);
    КонецЕсли;    
    
    Excel.Workbooks.Open(Объект.ПутьКФайлу);
    Если Не ЗначениеЗаполнено(Объект.НазванияСтраниц) Тогда
        НомерЛиста         = 1;
        Excel.Sheets(НомерЛиста).select();
        Excel.DisplayAlerts = 0;
        Версия = Лев(Excel.Version,Найти(Excel.Version,".")-1);
        Если Версия = "8" тогда
            ФайлСтрок   = Excel.Cells.CurrentRegion.Rows.Count;
            ФайлКолонок = Макс(Excel.Cells.CurrentRegion.Columns.Count, 13);
        Иначе
            ФайлСтрок   = Excel.Cells(1,1).SpecialCells(11).Row;
            ФайлКолонок = Excel.Cells(1,1).SpecialCells(11).Column;  
        Конецесли;
        Объект.КонечнаяСтрока=ФайлСтрок;
        Объект.КоличествоКолонок=ФайлКолонок;
        Если Объект.КоличествоКолонок<>0 Тогда
            ЗаполнитьЗначенияКолонок();
        КонецЕсли;
        мЭтотОбъект=РеквизитФормыВЗначение("Объект");
        Лист = Excel.Worksheets(НомерЛиста);
        ///////////////////////////////////////////////////////// реквизиты
        МассивРеквизитов = Новый Массив;
        МассивРеквизитов.Очистить();
        н=0;
        Для Каждого Колонка Из Объект.КолонкиИсточника Цикл
            н=н+1;
            МассивРеквизитов.Добавить(Новый РеквизитФормы(СокрЛП("Колонка"+строка(н)),Новый ОписаниеТипов("Строка"),"ТаблицаСДанными",СокрЛП(Колонка.Колонка)));
        КонецЦикла;
        
        ИзменитьРеквизиты(МассивРеквизитов);
        
        Результат = мЭтотОбъект.Читать_Эксель(Объект.КолонкиИсточника,Лист,Элементы,ТаблицаСДанными);
        Для Каждого Колонка Из Результат.Колонки Цикл
            Если Колонка.Имя="НомЭксель" Тогда Продолжить; КонецЕсли;
            НовыйЭлемент = Элементы.Добавить(Колонка.Имя, Тип("ПолеФормы"), Элементы.ТаблицаСДанными);
            НовыйЭлемент.Вид = ВидПоляФормы.ПолеВвода;
            НовыйЭлемент.ПутьКДанным = "ТаблицаСДанными." + Колонка.Имя;
        КонецЦикла;  
        
        ЗначениеВРеквизитФормы(Результат, "ТаблицаСДанными");
        
        //выбор листа
    Иначе
        
    КонецЕсли;
    КоличествоСтраниц=0;
    КоличествоСтраниц = Excel.Worksheets.Count;
    //ЭлементыФормы.СтрокаКоличествоСтраниц.Значение=КоличествоСтраниц;
    Если Не ЗначениеЗаполнено(Объект.НазванияСтраниц) Тогда
        Список=Новый СписокЗначений;
        Для i=1 По Excel.Worksheets.Count Цикл
            Список.Добавить(Excel.Worksheets(i).Name);
        КонецЦикла;
        Если Список.Количество() > 0 Тогда
            //Объект.НазванияСтраниц = Список.получить(Число(Список.Количество()-1));
            Объект.НазванияСтраниц = Список.получить(0);
        КонецЕсли;
    Иначе
        Для i=1 По Excel.Worksheets.Count Цикл
            Если СокрЛП(Объект.НазванияСтраниц)=СокрЛП(Excel.Worksheets(i).Name) Тогда
                НомерЛиста = Число(i);
            КонецЕсли;
        КонецЦикла;
        Если НомерЛиста=Неопределено или НомерЛиста=0 Тогда
        НомерЛиста=1;
        КонецЕсли;
        Excel.Sheets(НомерЛиста).select();
        Excel.DisplayAlerts = 0;
        Версия = Лев(Excel.Version,Найти(Excel.Version,".")-1);
        Если Версия = "8" тогда
            ФайлСтрок   = Excel.Cells.CurrentRegion.Rows.Count;
            ФайлКолонок = Макс(Excel.Cells.CurrentRegion.Columns.Count, 13);
        Иначе
            ФайлСтрок   = Excel.Cells(1,1).SpecialCells(11).Row;
            ФайлКолонок = Excel.Cells(1,1).SpecialCells(11).Column;  
        Конецесли;
        
        Объект.КонечнаяСтрока=ФайлСтрок;
        Объект.КоличествоКолонок=ФайлКолонок;
        Если Объект.КоличествоКолонок<>0 Тогда
            ЗаполнитьЗначенияКолонок();
        КонецЕсли;
        мЭтотОбъект=РеквизитФормыВЗначение("Объект");
        Лист = Excel.Worksheets(НомерЛиста);
        ///////////////////////////////////////////////////////// реквизиты
        МассивРеквизитов = Новый Массив;
        МассивРеквизитов.Очистить();
        н=0;
        Для Каждого Колонка Из Объект.КолонкиИсточника Цикл
            н=н+1;
            
            МассивРеквизитов.Добавить(Новый РеквизитФормы(СокрЛП("Колонка"+строка(н)),Новый ОписаниеТипов("Строка"),"ТаблицаСДанными",СокрЛП(Колонка.Колонка)));
        КонецЦикла;
        
        ИзменитьРеквизиты(МассивРеквизитов);
        
        Результат = мЭтотОбъект.Читать_Эксель(Объект.КолонкиИсточника,Лист,Элементы,ТаблицаСДанными);
        Для Каждого Колонка Из Результат.Колонки Цикл
            Если Колонка.Имя="НомЭксель" Тогда
                Продолжить;
            КонецЕсли;
            НовыйЭлемент = Элементы.Добавить(Колонка.Имя, Тип("ПолеФормы"), Элементы.ТаблицаСДанными);
            НовыйЭлемент.Вид = ВидПоляФормы.ПолеВвода;
            НовыйЭлемент.ПутьКДанным = "ТаблицаСДанными." + Колонка.Имя;
        КонецЦикла;  
        
        ЗначениеВРеквизитФормы(Результат, "ТаблицаСДанными");
        
    КонецЕсли;
    //Исключение
    //    Сообщить("Ошибка при открытии/чтении файла " + Объект.ЗагружаемыйФайл + "." + Символы.ПС + ОписаниеОшибки(), СтатусСообщения.Внимание);
    //КонецПопытки;
    Excel.ActiveWorkbook.Close();
    Excel.Quit();
    Возврат Истина;

КонецФункции

В реквизитах заведи Таблицу занчений (ТаблицаДанных)и в ней колонку НомЭксель (тип число)
Я думаю разберешься
17 Начинающий_13
 
24.03.16
10:57
Исполнение функции на сервере
18 DEaD_EGOR
 
24.03.16
10:58
(13) прост меня в ступор вводит сей момент.. Номенклатура в этом выражении берётся из эксельки и одновременно проверяется в справочнике на наличие позиции. а количество берётся из той же эксельки но ничем и нигде проверяться не должно... Мдааа. Учить и учить мне ещё программирование 1с)
19 MishaD
 
24.03.16
11:05
(18) ну количество проверяться должно, например на 0. да и грузится оно наверняка с неразрывным пробелом, надо это обрабатывать. А ссылочные типы - это не 1с, это вообще то базы данных.
20 DEaD_EGOR
 
24.03.16
12:10
(19) И всё равно я не могу понять, как в это выражение
&НаСервере
Функция ЗагрузитьПрайсНаСервере (Таблица,мФорма);
    
    Для Каждого СТР из Таблица Цикл
        
        НоваяСтрока = мФорма.Товары.Добавить();
        мНоменклатура = Справочники.Номенклатура.НайтиПоНаименованию(Стр.Номенклатура);
        Если мНоменклатура <> Справочники.Номенклатура.ПустаяСсылка() Тогда
        Новаястрока.Номенклатура = мНоменклатура;
        Иначе Новаястрока.Номенклатура = СоздатьНоменклатуруНаСервере(СТР.Номенклатура);
        КонецЕсли;
        
        КонецЦикла
КонецФункции
прикрутить заполнение цены и количества.... Если писать
НоваяСтрока = мФорма.Количество.Добавить, то добавляется новая строка после значения номенклатуры.. но это неправильно...