|
v7: Из XML Расходная накладная | ☑ | ||
---|---|---|---|---|
0
mcwolf
15.10.13
✎
21:56
|
Доброго времени суток! Уважаемые гуру подскажите чайнику =)
Питаюсь сделать обработку в 1с 7.7 Торговля+Склад, но что-то не выходит до конца доделать опыта не хватает (не судите строго я только начал изучать) Обработка: //Ограничения на входящие файлы XML: //1) В первой строке обязателен заголовок XML вида <?xml version="1.0" encoding="windows-1251"?> . //2) Каждый тег должен быть записан в отдельной строке. Возможны отступы от начала строки и пустые строки. //3) Значения атрибутов - строго в двойных кавычках. //4) Не поддерживаются текстовые значения (любые значения можно передавать только через атрибуты). //5) Комментарии и "подобные им" элементы XML не поддерживаются. перем xml_fso; перем xml_file; перем xml_ИмяТега; перем xml_СписокАтрибутов; перем xml_сз; /////////////////////////////////////////////////////////////////////// //Открывает XML-файл в режиме "только чтение" Процедура xml_ОткрытьФайл(прм_ИмяФайла) // прм_ИмяФайл="+ПутьФайла+"; //прм_ИмяФайла - имя файла XML (укажите полный путь и расширение .XML). xml_fso=СоздатьОбъект("Scripting.FileSystemObject"); xml_file=xml_fso.OpenTextFile(прм_ИмяФайла, 1, 0, 0); //Открываем файл в режиме "только чтение" стр=xml_file.ReadLine(); //Читаем заголовок XML вида <?xml version="1.0" encoding="utf-8"?>. Если Найти(стр,"<?xml")=0 Тогда Сообщить("Неправильный файл XML "+прм_ИмяФайла,"!"); а=10/0; КонецЕсли; Если Найти(стр,"utf-8")=0 Тогда Сообщить("Требуется кодировка UTF-8 файла XML "+прм_ИмяФайла,"!"); а=10/0; КонецЕсли; xml_СписокАтрибутов=СоздатьОбъект("СписокЗначений"); xml_сз=СоздатьОбъект("СписокЗначений"); КонецПроцедуры // xml_ОткрытьФайл /////////////////////////////////////////////////////////////////////// //Считывает следующий тег XML. //Возвращает 1, если тег прочитан и 0 - если был достигнут конец файла. //Заполняет переменную xml_ИмяТега именем считанного тега в формате "<ИмяТега>". Функция xml_Прочитать(прм_ОжидаемыеТеги="") //Если вы используете параметр прм_ОжидаемыеТеги, то заполните его списком тегов //через запятую, которые могут быть считаны в данный момент (это позволяет проверять //структуру файла XML и сделать более ясным считывающий код). xml_СписокАтрибутов.УдалитьВсе(); стр=""; Пока стр="" Цикл Если xml_file.AtEndOfStream=1 Тогда Возврат 0; //тег не был прочитан, т.к. достигнут конец файла КонецЕсли; стр=СокрЛП(xml_file.ReadLine()); КонецЦикла; //цикл, чтобы пропустить пустые строки Если Найти(стр,"=")=0 Тогда //Случай, когда нет атрибутов xml_ИмяТега=СокрЛП(стр); Иначе //Разбиваем тег на структуру, удобную для ИзСтрокиСРазделителями() стр=СтрЗаменить(стр,"""",""","""); стр=""""+стр+""""; сз=xml_сз; сз.УдалитьВсе(); сз.ИзСтрокиСРазделителями(стр); //В первом элементе списка у нас и имя тега, и имя первого атрибута. Разделим их. зн=сз.ПолучитьЗначение(1); поз=Найти(зн , " "); xml_ИмяТега =СокрЛП(Лев(зн, поз)); //Выделим имя тега xml_ИмяТега =xml_ИмяТега+">"; //Выделим и обновим имя первого атрибута зн =СокрЛП(Сред(зн, поз)); сз.УстановитьЗначение(1,зн); //Удаляем завершающий элемент списка /> или >. сз.УдалитьЗначение(сз.РазмерСписка()); //Переводим наш список значений в более удобный формат i=1; //позиция в списке сз рс=сз.РазмерСписка(); Пока i<=рс Цикл имя=сз.ПолучитьЗначение(i); имя=СокрЛП(СтрЗаменить(имя,"=","")); зн=сз.ПолучитьЗначение(i+1); //Заменяем спецсимволы XML зн=СтрЗаменить(зн,"&"+"quot"+";",""""); зн=СтрЗаменить(зн,"&"+"apos"+";","'"); зн=СтрЗаменить(зн,"&"+"lt"+";","<"); зн=СтрЗаменить(зн,"&"+"gt"+";",">"); зн=СтрЗаменить(зн,"&"+"amp"+";","&"); xml_СписокАтрибутов.ДобавитьЗначение(зн,имя); i=i+2; КонецЦикла; КонецЕсли; Если ПустаяСтрока(прм_ОжидаемыеТеги)=0 Тогда //Проверяем наличие имени тега в списке ожидаемых тегов (если надо контролировать структуру) //*Если Найти(прм_ОжидаемыеТеги,xml_ИмяТега)=0 Тогда //* Сообщить("Неожиданный тег "+xml_ИмяТега+" в строке "+xml_file.line); a=10/0; //*КонецЕсли; КонецЕсли; Возврат 1; //успешное чтение тега КонецФункции // xml_Прочитать /////////////////////////////////////////////////////////////////////// //Получает значение атрибута считанного тега по имени атрибута. //Если надо получить атрибут по его номеру, читайте список значений xml_СписокАтрибутов Функция xml_ПолучитьАтрибут(прм_ИмяАтрибута) Возврат xml_СписокАтрибутов.Получить(прм_ИмяАтрибута); КонецФункции // xml_ПолучитьАтрибут /////////////////////////////////////////////////////////////////////// //Закрывает открытый файл XML. По завершении работы с файлом его необходимо закрыть. Функция xml_Закрыть() xml_file.Close(); КонецФункции // xml_Закрыть //******************************************* //Тестовая процедура, которая считывает XML файл в справочник Товаров. Процедура Выполнить() стрИмяФайла=КаталогИБ()+"XML\tovar.xml"; спр=СоздатьОбъект("Справочник.Номенклатура"); НачатьТранзакцию(); //Для ускорения сч=0; //Для ускорения Сообщить("Начало чтения XML: "+ТекущееВремя()); xml_ОткрытьФайл(стрИмяФайла); xml_Прочитать("<gw_srv_rsp>"); xml_Прочитать("<DAT>"); xml_Прочитать("</P>"); СпрТовары=СоздатьОбъект("Справочник.Номенклатура"); спрР=СоздатьОбъект ("Документ"); спрР=СоздатьОбъект("Документ.РасходнаяНакладная"); спрР.Новый (); Пока xml_Прочитать("<DAT>,<P>,</P>,<E>,<N>,<TS>,</gw_srv_rsp>")=1 Цикл сч=сч+1; //Для ускорения Если сч%1000=0 Тогда //Для ускорения ЗафиксироватьТранзакцию(); //Для ускорения НачатьТранзакцию();//Для ускорения КонецЕсли;//Для ускорения Если xml_ИмяТега="</gw_srv_rsp>" Тогда Прервать; КонецЕсли; Код=Число(xml_ПолучитьАтрибут("C")); Товар=xml_ПолучитьАтрибут("NM"); Количество=Число(xml_ПолучитьАтрибут("Q")); Цена=Число(xml_ПолучитьАтрибут("PRC")); ДатаОплаты=xml_ПолучитьАтрибут("ДатаОплаты"); КолВоВНанк=Число(xml_ПолучитьАтрибут("N")); спрР=СоздатьОбъект ("Документ"); спрР=СоздатьОбъект("Документ.РасходнаяНакладная"); спрР.ВыбратьСтроки(); спрР.Новый (); спрР.ВыбратьСтроки(); спрР.НоваяСтрока (); спрР.Товар = СпрТовары.ТекущийЭлемент (); спр=СоздатьОбъект("Справочник.Номенклатура"); Если спр.НайтиПоНаименованию(Товар)=1 Тогда //Предупреждение("Найденный элемент справочника имеет код "+спр.ТекущийЭлемент().ПолнНаименование); Сообщить ("Добавлена строка с товаром: " +спр.ТекущийЭлемент().ПолнНаименование); спрР.Товар = спр.ТекущийЭлемент(); спрР.Количество = Количество/1000; спрР.ЦенаСНДС = Цена; спрР.ЦенаБезНДС = Цена-(Цена*20/100); спрР.СуммаБезНДС =(Количество/1000)*(Цена-(Цена*20/100)); спрР.СуммаСНДС = (Количество/1000)*Цена; спрР.ДатаОплаты = xml_ПолучитьАтрибут("TS"); //ДатаОплаты; Если xml_Прочитать("</DAT>")=1 Тогда спрР.Записать(); Продолжить; Иначе //Предупреждение("Элемент с заданным наименованием не найден"); Сообщить ("Элемент с заданным наименованием не найден: " +Товар); Продолжить; КонецЕсли; КонецЕсли; КонецЦикла; //по элементам XML xml_Закрыть(); Сообщить("Обработка завершена! "+ТекущееВремя(),"i"); ЗафиксироватьТранзакцию(); //Для ускорения КонецПроцедуры процедура приОткрытии() ПутьФайла = КаталогИБ()+"XML\tovar.xml"; КонецПроцедуры и собственно сам XML: <?xml version="1.0" encoding="utf-8"?> <gw_srv_rsp> <select> <FISC V="1"> <EJ ID="ПБ4101217109"> <DAT DI="20" FN="2659024340" KI="1" TN="ПН 164775926121" V="1" ZN="ПБ4101217109"> <C T="0"> <P C="59" CD="2000000059013" N="1" NM="Диск дл циркулярної пилки KT 125 (24T)" PRC="2440" Q="1000" SM="2440" TX="1"></P> <P C="60" CD="2000000060019" N="2" NM="Диск дл циркулярної пилки KT 125 (40T)" PRC="3242" Q="1000" SM="3242" TX="1"></P> <P C="1270" CD="2000001270011" N="3" NM="Свердло по металу P9 (Росія) d.4.2мм" PRC="646" Q="10000" SM="6460" TX="1"></P> <M N="4" SM="12142" T="0"> </M> <E CS="1" N="5" NO="4" SM="12142"> <TX DTPR="0.00" TX="1" TXPR="20.00" TXSM="2024" TXTY="0"></TX> </E> </C> <TS>20130803152414</TS> </DAT><DAT DI="159" FN="2659024340" KI="1" TN="ПН 164775926121" V="1" ZN="ПБ4101217109"> <C T="0"> <P C="31" CD="2000000031019" N="1" NM="Клей SOMA FIX (супер клей) 3гр. 808E" PRC="289" Q="3000" SM="289" TX="1"></P> <P C="227" CD="2000000227016" N="2" NM="Мом 25 Клеюча суміш для плитки Момент, 25 кг" PRC="4079" Q="1000" SM="4079" TX="1"></P> <M N="2" SM="289" T="0"></M> <E CS="1" N="3" NO="108" SM="289"> <TX DTPR="0.00" TX="1" TXPR="20.00" TXSM="48" TXTY="0"></TX> </E> </C> <TS>20130810124726</TS> </DAT> </EJ> </FISC> </select> </gw_srv_rsp> Получается есть теги <DAT>....</DAT> между этих тегов есть <P>...</P> но их может быть несколько но добавляет только первый. Как сделать так чтоб расходная накладная создавалась со всеми позициями указаними в тегах <DAT>....</DAT>? |
|||
1
Тьма
15.10.13
✎
22:36
|
Для начала было бы неплохо исправить некоторые ошибки
1. По условию Если xml_Прочитать("</DAT>")=1 Тогда предполагается, что xml_Прочитать возвращает 0, если данный тег не найден в следующей строке. Однако 0 возвращается только в случае конца файла. 2. Делать цикл по условию на итератор (пока получить строку файла) и внутри цикла менять этот итератор (уже упомянутое условие) - дурной тон. У тебя каждая вторая строка в файле из-за этого не обрабатывается. 3. Ветвление с сообщением Сообщить ("Элемент с заданным наименованием не найден: " +Товар); не в том условии. Там 2 Если и по смыслу это счастье должно быть в первом. 4. Поиск по наименованию - это плохо. Там код в файле для этого есть. Разумеется, код не должен быть доступен пользователю для изменения. П.С. Лично я разбор этого файла со шлюза делаю так: После посылки АШТТП запроса получаю ответ в одну переменную и работаю с ней. В этой переменной ищу теги DAT и /DAT, выделяю таким образом один чек. Уже в этом чеке ищу строчку "P C=" (или можно так же выделять по очереди по тегу <Р> </Р>) и уже в нем ищу код, цену и количество. Там будут еще нюансы, связанные с возвратными чеками, отменой чека, скидками в чеке (если в Т400 не запрещены скидки, что стоит сделать). Возможно, будет еще много других нюансов, так как описания формата этого файлика в глаза не видел :) |
|||
2
mcwolf
15.10.13
✎
23:00
|
Спасибо за столь обширный ответ. Я мало чего понял :)) но понял что я еще очень далеко от истины =)
|
|||
3
mcwolf
15.10.13
✎
23:57
|
И еще вопросик есть компонента ecrT400.dll есть пример работы с 1С 8
Код проверен на версии ecrT400.dll — 1.0.4.515, 1С версии 8.2.16.362. Приведенный пример кода написан для управляемого приложения. //подключение компоненты ПодключитьВнешнююКомпоненту(«ecrmini.t400?); //создаем соединение с компонентой для отправки команд Connection = Новый COMОбъект(«ecrmini.t400?); //команда открытия порта Result = Connection.t400me(«open_port;1;115200?); Если НЕ Result Тогда КодОшибки = Connection.get_last_error(); Результат = «Ошибка соединения МИНИ Т400: «+КодОшибки; КонецЕсли; Аналогично запускаются и остальные команды, методом t400me(). Может кто-то видел код для 7-ки? |
|||
4
Тьма
16.10.13
✎
09:15
|
(2)Я заметил, что ты не используешь 1с-ные функции работы со строками Найти и Сред. Может, с ними будет попроще? Что-то типа:
Если Найти(ТекСтрока,"<P>")<>0 тогда //строка продажи из чека Поз1=найти(ТекСтрока," C=");//позиция, с которой начинается код Поз2=Найти(Текстрока," CD=");//позиция, с которой начинается штрихкод Код=Сред(ТекСтрока,Поз1+4,Поз2-Поз1-5); ///и так далее (3)Делаю все обычным АШТТП запросом, без ВК. Вот так продажи получаю. Правда, с четвертой версией шлюза этот код перестал работать, но меня пока устраивает третья :) Дата1=""+ДатаГод(НачДата)+Прав("00"+ДатаМесяц(НачДата),2)+Прав("00"+ДатаЧисло(НачДата),2)+"0000"; Дата2=""+ДатаГод(КонДата)+Прав("00"+ДатаМесяц(КонДата),2)+Прав("00"+ДатаЧисло(КонДата),2)+"2359"; Сервер="http://10.0.0.101:12702/lsoft"; WinHttp=СоздатьОбъект("WinHttp.WinHttpRequest.5.1"); WinHttp.Open("POST",Сервер,0); WinHttp.setRequestHeader("Content-type", "text/xml"); WinHttp.setRequestHeader("Content-length", "34077"); xml="<?xml version="+Симв(34)+"1.0"+Симв(34)+" encoding="+Симв(34)+"utf-8"+Симв(34)+"?>"+Разделительстрок; xml=xml+"<srv_req>"+Разделительстрок; xml=xml+"<select from ="+Симв(34)+Дата1+Симв(34)+" to="+Симв(34)+Дата2+Симв(34)+">"+Разделительстрок; спр1=создатьобъект("Справочник.КассовыеАппараты"); спр1.выбратьэлементы(); Пока спр1.получитьэлемент()=1 цикл Если ПустоеЗначение(Спр1.Магазин)=1 Тогда продолжить; КонецЕсли; Если сокрлп(Спр1.Фискальныйномер)="" Тогда продолжить; КонецЕсли; Если спр1.пометкаудаления()=1 Тогда продолжить; КонецЕсли; Если (магазин.выбран()=1)и(Спр1.Магазин<>Магазин) Тогда продолжить; КонецЕсли; Если ПустоеЗначение(Спр1.касса)=1 Тогда продолжить; КонецЕсли; xml=xml+"<dev sn="+Симв(34)+ПреобразоватьСтрокуВУТФ8(сокрлп(Спр1.Фискальныйномер))+Симв(34)+"/>"+Разделительстрок; конеццикла; xml=xml+"</select>"+Разделительстрок; xml=xml+"</srv_req>"; Тк=создатьобъект("Текст"); Тк.ДобавитьСтроку(xml); тк.записать("c:\temp\zapr.xml"); WinHttp.SetTimeouts(1000000,1000000,1000000,1000000); WinHttp.Send(xml); WinHttp.WaitForResponse(-1); ответ=WinHttp.ResponseText; ответ1=WinHttp.StatusText; |
|||
5
Тьма
16.10.13
✎
09:16
|
+(4)И да, ПреобразоватьСтрокуВУТФ8 можно заменить просто на сокрлп - там с кодировками некая шняга, в заголовке указан УТФ, а принимает файл только в АНСИ. Хотя если руками загружать на шлюз, нужен УТФ. :)
|
|||
6
Тьма
16.10.13
✎
09:20
|
(3)Если сильно хочешь через ВК, то отличия для 7.7 невелики:
вместо ПодключитьВнешнююКомпоненту(«ecrmini.t400?); пишешь ЗагрузитьВнешнююКомпоненту(ПутьКДЛЛФайлуВнешнейКомпоненты); и вместо Connection = Новый COMОбъект(«ecrmini.t400?); пишешь Connection = СоздатьОбъект("ecrmini.t400"); |
|||
7
mcwolf
16.10.13
✎
21:05
|
Насколько я понял можно еще юзать ecrT400.dll и можно будет вытащить нужные данные со шлюза? Или есть другие способы чтения отчётов Мини Т400, потому что за день много продаж а вручную вбивать пипец как долго...
|
|||
8
Тьма
16.10.13
✎
21:16
|
(7)Есть и другие. В (4) есть пример ХТТП-запроса к шлюзу. Также этот метод описан в документации по ссылке http://unisystem.ua/ru/product/avtomat/support/shluz-unisystem.html. Кроме того, непосредственно в интерфейсе шлюза можно выгрузить ручками же хмл-файл с продажами или же эксель-файл с теми же данными - если работа с экселем по каким-то причинам представляется более предпочтительной.
|
|||
9
mcwolf
16.10.13
✎
22:33
|
Если тебе не сложно можешь показать как пользоваться твоими указаниями(4) на моём примере?
|
|||
10
mcwolf
16.10.13
✎
22:37
|
Давно работаешь с мини т400? Как загружаешь товары обработкой?
|
|||
11
mcwolf
17.10.13
✎
00:05
|
Могу поделится обработкой :)
|
|||
12
Тьма
17.10.13
✎
09:15
|
(9)Ну... а что неясно в (4)? По поводу твоего примера - надо заменить
//// Если xml_Прочитать("</DAT>")=1 Тогда спрР.Записать(); Продолжить; Иначе //Предупреждение("Элемент с заданным наименованием не найден"); Сообщить ("Элемент с заданным наименованием не найден: " +Товар); Продолжить; КонецЕсли; //////// на ///// спрР.Записать(); /////// это не вполне оптимально, но работать должно лучше. (10)С февраля 2013. На шлюз третьей версии ХТТП-запросом, единственно что 1с не умеет посылать ХТТП-запросы размером более 500Кб, по подсказке с этого форума отправляю vbs-скриптом, который, впрочем, все равно создается и вызывается из 1С. На шлюз четвертой - формируется хмл и оператор ручками на шлюзе его грузит. (11)Их есть у меня :) |
|||
13
mcwolf
17.10.13
✎
10:19
|
(12) Если сделать замену ка ты говоришь то на каждую позицию создается новая накладная, а нужно чтоб создавалась накладная согласно <DAT>...</DAT>, Если поставить "Если xml_Прочитать("</DAT>")=1 Тогда" то года оно разбивает по <DAT>...</DAT> но считывает только первые <P> а остальные пропускает.
|
|||
14
monsterZE
17.10.13
✎
10:43
|
все не читал.. но в чем проблема? =)
читаешь строки при <DAT> поднимаешь флаг нового документа пока не </DAT> пихаешь строки в документ по <p></p> вот тебе для примера.. что-то аналогичное только у меня собирается в тз и по колонкам тз_на_форме выводится нужное (чтоб прощее добавлять новое) Состояние("Загрузка файла обмена ПП"); СтрокТФ = ТФ.КоличествоСтрок(); НовоеПП = 0; Для ъ=1 По СтрокТФ Цикл ТФСтр = ТФ.ПолучитьСтроку(ъ); Если СтрДлина(ТФСтр)=0 Тогда Продолжить; КонецЕсли; Если НовоеПП=0 Тогда // начало ПП Если Найти(ТФСтр,"СекцияДокумент=Платежное поручение")=1 тогда НовоеПП = 1; ТабТекПП.Очистить(); ТабТекПП.НоваяКолонка("ПарамИмя"); ТабТекПП.НоваяКолонка("ПарамЗнач"); КонецЕсли; Иначе // конец ПП Если Найти(ТФСтр,"КонецДокумента")=1 тогда ВыгрВТаб(ТабТекПП,СписокКолонокПП,ВремТаб); НовоеПП = 0; Иначе // строки ПП Если ДобавитьЗначВТаб(ТабТекПП,ТФСтр,"=")=1 Тогда Предупреждение("Ошибка в структуре файла обмена, текущее ПП пропущено",5); Сообщить("-- Ошибочное ПП --"); ТабТекПП.ВыбратьСтроки(); Пока ТабТекПП.ПолучитьСтроку()=1 Цикл Сообщить(ТабТекПП.ПарамИмя+"="+ТабТекПП.ПарамЗнач); КонецЦикла; НовоеПП = 0; КонецЕсли; КонецЕсли; КонецЕсли; КонецЦикла; |
|||
15
Тьма
17.10.13
✎
19:19
|
(13)Убери из цикла
/////// спрР=СоздатьОбъект ("Документ"); спрР=СоздатьОбъект("Документ.РасходнаяНакладная"); спрР.ВыбратьСтроки(); спрР.Новый (); спрР.ВыбратьСтроки(); ///////// и не будет на каждую строчку новый документ создавать |
|||
16
mcwolf
17.10.13
✎
23:45
|
(15) В принципе то оно так но теперь все записывается в одну накладную... а нужно чтоб на каждый <DAT> создавалась новая накладная.
|
|||
17
mcwolf
18.10.13
✎
00:11
|
(14) Спасибо Вам за ответ но я вернусь к первому посту "не судите строго я только начал изучать"
|
|||
18
mcwolf
18.10.13
✎
01:41
|
(16) Ах да и еще забыл записывает в одну накладную и все равно только первые позиции <P> остальные пропускает...
|
|||
19
Тьма
18.10.13
✎
09:24
|
(18)Сейчас досмотрелся - это чудо юнисистемское пишет каждый чек в одну строчку. Ну а твой код из каждой строчки берет только один товар. Так что твоя процедурка xml_Прочитать этого не отработает и придется тебе писать два цикла - один по строкам, а второй по поиску в текущей строке открывающего и закрывающего тега <P>. Потом уже вырванную серединку можешь скормить своей процедуре. После нахождения первого закрывающего тега обрезаешь строку справа и ищешь в новой строке и т.д. пока все теги <P> не будут найдены. Смотри описание функция работы со строками Найти и Сред.
|
|||
20
mcwolf
19.10.13
✎
10:15
|
(19) Будем читать...
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |