Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Загрузка прайса из Экселя
Украинский 1С форум: всё про 1С 8.3, 1С 8.2, 1С 8.1, 1С 8.0, 1С 7.7 > Программисту > Программирование в 1С Предприятие 7.7
igmig65
Есть обработка по загрузке прайсов. Но....В прайсе более 30 тыс. позиций. Работает очень медленно, так как приходится работать методом НайтиПоРеквизиту(). Конфигурация доработана. Есть реквизит КодДляЗагрузки, вот по нему и ищем. Если создается новый, то вводится и элемент и несколько подчиненных (ед.изм, цены, категории и т.д.), если находит, то нужно обновлять цену. Интересно можно ли как нибудь оптимизировать решение этой задачи. Может кто сталкивался с подобным. Ведь приходится при получении строки экселя каждый раз запускать поиск по реквизиту по всему справочнику. Интересно, если например сначала выгрузить всю номенклатуру в список значений с представлением - КодомДляЗагрузки, и потом например проверять методом Получить(). Если получит то Найти() иначе Новый(). Даст ли это что нибудь в плане оптимизации....Может кто посоветует что другое. Так как прайсы грузятся в день по нескольку раз, разные, в разные каталоги.
Ardi
Даст прирост раз в 50-100. Не больше.
igmig65
Ну и то дело, а то по 2 часа грузятся
Ardi
LOL

А ещё таблицу эксель можно целиком грузить в ТЗ. Хотя это наверно в восьмёрке.
Домовик
Интересная идея. не знаю, оптимальнее ли будет. А если загрузить в список, а этот список использовать в условии в запросе?
Ardi
А реквизит вообще индексируемый?
g789
В качестве офтопа, если есть 1с++ то как-то так:
    Excel = СоздатьОбъект("Excel.Application"); 
    Excel.Displayalerts = 0;//отключить встроенные предупреждения Excel
    
    Excel.Workbooks.Open(СокрЛП(имяФайла));
    Excel.Worksheets(1).Activate();
    Excel.Range("B2").CurrentRegion.Select();//Выделить область
    tbl = Excel.ActiveCell.CurrentRegion;
    str = tbl.AddressLocal();
    str = "$" + СтрЗаменить(str,"$","");
    ListName = Excel.Worksheets(1).Name;
    стр = ListName + str;
    Excel.ActiveWindow.Close();

    Состояние("Считывание файла excel...");
    _база =СоздатьОбъект("ODBCDatabase");
    Если _база.Соединение("DRIVER=Microsoft Excel Driver (*.xls); DBQ=" +СокрЛП(имяФайла)) =0 Тогда
        Предупреждение("Ошибка открытия файла", 60);
        Возврат;
    КонецЕсли;
    _рс =СоздатьОбъект("ODBCRecordSet");
    _рс.УстБД(_база);
    ТекстЗапроса ="
    |select  *
    |from ["+стр+"]
    |";
    
    ит = _рс.ВыполнитьИнструкцию(ТекстЗапроса);
Ziam
Как вариант, читать файл в таблицу значений. А потом запросом выгребать из справочника инфу. Выиграете на сколько не знаю. Но обращение к базе будет одно, а не каждый раз. Как-то так
igmig65
Всем спасибо, со списком выиграл...но совсем немного. 1с++ неставил. Придется грузить только на серваке, там хоть машина серьезная, 4 ядра, в 4 раза быстрей грузит, чем на моей. Попробую еще сначала выгрузить в ТЗ, потом коды в список и запросом с условием по списку. Результат выложу.
dmiter
1. Файл в таблицу значений - сортировать по реквизиту (или можно отсортировать по реквизиту в Excel);
2. Справочник в таблицу значений - сортировать по реквизиту.
3. Проходим по строкам тз файла (или файлу), если реквизит 1-й строки тз справочника < реквизита файла тогда удаляем строку, если равна устанавливаем цену и удаляем строку с переходом на новую строку тз файла, иначе новый элемент.

При таком алгоритме проходов по справочнику и файлу будет m+n, при поиске элементов m*n.
m-количество строк в файле n - количество элементов справочника
Должно дать эффект.
g789
igmig65
Можно так, без 1с++ (имяФайла - реквизит формы, тбл - ТаблицаЗначений на форме)
    Если ФС.СуществуетФайл(СокрЛП(имяФайла))=0 Тогда
        Возврат;
    КонецЕсли;
    тбл.Очистить();
    
    Excel = СоздатьОбъект("Excel.Application");
    Excel.Displayalerts = 0;//отключить встроенные предупреждения Excel
    
    Excel.Workbooks.Open(СокрЛП(имяФайла));
    Excel.Worksheets(1).Activate();
    Excel.Range("B2").CurrentRegion.Select();//Выделить область
    tbl = Excel.ActiveCell.CurrentRegion;
    str = tbl.AddressLocal();
    str = "$" + СтрЗаменить(str,"$","");
    ListName = Excel.Worksheets(1).Name;
    стр = ListName + str;
    Excel.ActiveWindow.Close();

    Состояние("Считывание файла excel...");

    СтрокаПодключения ="DRIVER=Microsoft Excel Driver (*.xls); DBQ=" +СокрЛП(имяФайла);

    ТекстЗапроса ="
    |select  *
    |from ["+стр+"]
    |";

    Connection = СоздатьОбъект("ADODB.Connection");
    // Подключение к источнику данных
    Попытка
        Connection.Open(СтрокаПодключения);
    Исключение
        Сообщить(ОписаниеОшибки());
        Возврат;
    КонецПопытки;
    
    Command = СоздатьОбъект("ADODB.Command");
    Command.ActiveConnection = СтрокаПодключения;
    Command.CommandText = ТекстЗапроса;
    Command.CommandType = 1;
    // Создание объекта набора записей
    RecordSet = СоздатьОбъект("ADODB.RecordSet");
    // Выполнение и получение набора данных
    RecordSet.Open(Command);
    КоличествоПолей = RecordSet.Fields.Count;
    спИменаПолей = СоздатьОбъект("СписокЗначений");
    Для НомерКолонки = 0 По КоличествоПолей-1 Цикл
        ИмяПоля = RecordSet.Fields.Item(НомерКолонки).Name;
        спИменаПолей.ДобавитьЗначение(ИмяПоля);
        тбл.НоваяКолонка(ИмяПоля);
    КонецЦикла;

    // Перебор данных
    Пока RecordSet.EOF() = 0 Цикл
        тбл.НоваяСтрока();
        Для н=1 По КоличествоПолей Цикл
            тбл.УстановитьЗначение(тбл.НомерСтроки,н,RecordSet.Fields(н-1).Value);
        КонецЦикла;
        RecordSet.MoveNext();
    КонецЦикла;
    RecordSet.Close ();
    Connection.Close();

но так буде медленее, долго заполняется таблица
igmig65
Сделал: ч-з запрос выгружаю справочник в ТЗ и потом перебирая строки эксель использую ТЗ.НайтиЗначение(). Работает в 40 раз быстрее, единственное это выполнение самого запроса, так как позиций выгружается порядка 30 тыс. Но всеравно результат есть...ВСЕМ СПАСИБО.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.