Группа: Местный
Сообщений: 2908
Из: Київ, Україна
Спасибо сказали: 1159 раз
Рейтинг: 1244.5
В основном ПостроительDOM, ДокументDOM. Это как бы аналог "Msxml2.DOMDocument". И если уж минимизировать переписывание кода, то проще это делать в одной плоскости. XDTO - это уже более высокий уровень работы 1с с xml, для которого существует достаточно много ограничений.
Допрацьовую: - "Бухгалтерія для України 2.1"; - "Альфа-Авто: Автосалон+Автосервіс+Автозапчастини, українська версія".
// формируем имя файла //данные всегда берутся из служебной области Если Сред (ИмяСхемы,1,4) = "JFSS" Тогда КодВФонде = СокрЛП(спПараметры.ДанныеОтчета.ПолеТабличногоДокументаОтчетФССУтратаТрудосп.CSTRAX); ИмяФайла = "Z" + КодВФонде + ".xml"; Иначе КодНалоговой = ДополнитьСтрокуСимволами(СокрЛП(Формат(спПараметры.ДанныеОтчета.ПолеТабличногоДокументаСлужебныеДанные.C_STI,"ЧЦ=4;ЧГ=0")),"0",4 ,1); // дополним нулями слева
КодНалоговойОриг = ""; Если НЕ спПараметры.ДанныеОтчета.ПолеТабличногоДокументаСлужебныеДанные.Свойство("C_STI_ORIG", КодНалоговойОриг) Тогда КодНалоговойОриг = КодНалоговой; КонецЕсли; КодНалоговойОриг = ДополнитьСтрокуСимволами(СокрЛП(Формат(КодНалоговойОриг,"ЧЦ=4;ЧГ=0")),"0",4 ,1);
// поддержка выгрузки многостраничных отчетов текC_DOC_CNT = Неопределено; Если НужнаяСтруктура.Свойство("C_DOC_CNT", текC_DOC_CNT) Тогда НомерВПериоде = ДополнитьСтрокуСимволами(Строка(текC_DOC_CNT),"0",7 ,1); Иначе НомерВПериоде = ДополнитьСтрокуСимволами(Строка(мC_DOC_CNT),"0",7 ,1); КонецЕсли;
ТипПериода= ""; Если НЕ спПараметры.ДанныеОтчета.ПолеТабличногоДокументаСлужебныеДанные.Свойство("PERIOD_TYPE", ТипПериода) Тогда ТипПериода = 1; КонецЕсли; ТипПериода = СОКРЛП(Лев(ТипПериода,1));
// новый порядок формирования имени файла ИмяФайла = КодНалоговой + КодФирмы + ИмяСхемы+ СостояниеОтчета + ТипОтчета + НомерВПериоде + ТипПериода + МесяцПериода + ГодПериода + КодНалоговойОриг + ".xml";
КонецЕсли;
Сообщить(НСтр("ru='- Начало выгрузки в файл ';uk='- Початок вивантаження у файл '")+ ИмяФайла);
Попытка ДокЭкспорт = Новый COMОбъект("Msxml2.DOMDocument.4.0"); Исключение Попытка ДокЭкспорт = Новый COMОбъект("Msxml2.DOMDocument.3.0"); Исключение фОшибка = 1; Возврат; КонецПопытки; КонецПопытки;
pi =ДокЭкспорт.createProcessingInstruction("xml", "version=""1.0"" encoding=""windows-1251"""); ДокЭкспорт.insertBefore(pi, ДокЭкспорт.childNodes.item(0));
Если Сред (ИмяСхемы,1,4) = "JFSS" Тогда //Если это РегламентированныйОтчетФСС тогда // ДокЭкспорт.createProcessingInstruction("encoding", "'windows-1251'"); //Если это не первый квартал, то открываем уже сформированный файл и дописываем в него //если открыть не удалось - ошибка. Если НЕ ЗначениеЗаполнено(ПолучитьИзСтруктуры("P1", НужнаяСтруктура)) Тогда Если НЕ ДокЭкспорт.Load(КаталогДанныхЭкспорта + "\" + ИмяФайла) Тогда Сообщить(НСтр("ru='Не удалось открыть файл отчета за первый квартал для добавления данных!" "Для экспорта нужно создать новый файл!';uk='Не вдалося відкрити файл звіту за перший квартал для додавання даних!" "Для експорту потрібно створити новий файл!'"), СтатусСообщения.Важное); //--------------------------- Если Вопрос(НСтр("ru='Создать новый файл?';uk='Створити новий файл?'"), РежимДиалогаВопрос.ДаНет) = КодВозвратаДиалога.Нет Тогда Возврат; КонецЕсли; // главный элемент F4 элДокумента = ДокЭкспорт.createElement("F4"); ДокЭкспорт.appendChild(элДокумента);
Для Каждого СтрокаШапки из тбПоказателиШапка Цикл ВыгрузитьПоказатель(элДокумента, СтрокаШапки.Имя, ПреобразоватьТипXML(ПолучитьИзСтруктуры(СтрокаШапки.Имя, НужнаяСтруктура),СтрокаШапки.Тип,ИмяСхемы)); Если (СтрокаШапки.Имя = "DATA") Тогда НовыйЭлемент = ДокЭкспорт.createElement(СтрокаШапки.Имя); элДокумента.appendChild(НовыйЭлемент); ЭлементСДанными = НовыйЭлемент; Для Каждого СтрокаТела Из тбПоказателиТело Цикл НовыйЭлемент = ДокЭкспорт.createElement(СтрокаТела.Имя); ЭлементСДанными.appendChild(НовыйЭлемент);
ЭлементНужногоКвартала = НовыйЭлемент; тбПоказателиТаблицы = СтрокаТела.Таблица; Если ПолучитьИзСтруктуры(СтрокаТела.Имя, НужнаяСтруктура) = "" Тогда Для Каждого строка Из тбПоказателиТаблицы Цикл ВыгрузитьПоказатель(ЭлементНужногоКвартала, строка.Имя, ПреобразоватьТипXML(Неопределено,строка.Тип,ИмяСхемы)); КонецЦикла; ВыгрузитьПоказатель(ЭлементНужногоКвартала, строка.Имя, "0,"); Иначе Для Каждого строка Из тбПоказателиТаблицы Цикл ВыгрузитьПоказатель(ЭлементНужногоКвартала, строка.Имя, ПреобразоватьТипXML(ПолучитьИзСтруктуры(строка.Имя, НужнаяСтруктура),строка.Тип,ИмяСхемы)); КонецЦикла; КонецЕсли; КонецЦикла; КонецЕсли; КонецЦикла;
ВыгрузитьПоказатель(элДокумента, "DATAF14",); //--------------------------- Иначе // Тут нужно разбирать загруженный файл, и писать в него необходимые данные УзКорень=ДокЭкспорт.DocumentElement; //УзОтношенияСписок=УзКорень.SelectNodes("//*[name()='Data']"); Для ИндКор=1 По УзКорень.childNodes.Length Цикл УзОтношение=УзКорень.childNodes.item(ИндКор-1); Если ВРег(УзОтношение.BaseName)=ВРег("Data") Тогда //Перебираем закладки P1-P4 Для ИндКор2 = 1 По УзОтношение.childNodes.length Цикл УзелР = УзОтношение.childNodes.item(ИндКор2-1); //Теперь мы "внутри" одного из разделов //выбираем нужный, и пишем в него данные. Если НЕ ЗначениеЗаполнено(ПолучитьИзСтруктуры(тбПоказателиТело[ИндКор2-1].Имя, НужнаяСтруктура)) Тогда // сюда прописываем действия производимые с "другими периодами" Иначе Для Инд=1 По УзелР.childNodes.length Цикл УзелР.removechild(УзелР.childNodes.item(0)); КонецЦикла; тбПоказателиТаблицы = тбПоказателиТело[ИндКор2-1].Таблица; Для Каждого строка Из тбПоказателиТаблицы Цикл ВыгрузитьПоказатель(УзелР, строка.Имя, ПреобразоватьТипXML(ПолучитьИзСтруктуры(строка.Имя, НужнаяСтруктура),строка.Тип,ИмяСхемы)); КонецЦикла КонецЕсли; КонецЦикла; КонецЕсли; КонецЦикла; КонецЕсли; Иначе // Если это первый квартал, то создаём новый файл
// главный элемент F4 элДокумента = ДокЭкспорт.createElement("F4"); ДокЭкспорт.appendChild(элДокумента);
Для Каждого СтрокаШапки из тбПоказателиШапка Цикл ВыгрузитьПоказатель(элДокумента, СтрокаШапки.Имя, ПреобразоватьТипXML(ПолучитьИзСтруктуры(СтрокаШапки.Имя, НужнаяСтруктура),СтрокаШапки.Тип,ИмяСхемы)); Если (СтрокаШапки.Имя = "DATA") Тогда НовыйЭлемент = ДокЭкспорт.createElement(СтрокаШапки.Имя); элДокумента.appendChild(НовыйЭлемент); ЭлементСДанными = НовыйЭлемент; Для Каждого СтрокаТела Из тбПоказателиТело Цикл НовыйЭлемент = ДокЭкспорт.createElement(СтрокаТела.Имя); ЭлементСДанными.appendChild(НовыйЭлемент); ЭлементНужногоКвартала = НовыйЭлемент; тбПоказателиТаблицы = СтрокаТела.Таблица; Если ПолучитьИзСтруктуры(СтрокаТела.Имя, НужнаяСтруктура) = "" Тогда Для Каждого строка Из тбПоказателиТаблицы Цикл ВыгрузитьПоказатель(ЭлементНужногоКвартала, строка.Имя, ПреобразоватьТипXML(Неопределено,строка.Тип,ИмяСхемы)); КонецЦикла; ВыгрузитьПоказатель(ЭлементНужногоКвартала, строка.Имя, "0,"); Иначе Для Каждого строка Из тбПоказателиТаблицы Цикл ВыгрузитьПоказатель(ЭлементНужногоКвартала, строка.Имя, ПреобразоватьТипXML(ПолучитьИзСтруктуры(строка.Имя, НужнаяСтруктура),строка.Тип,ИмяСхемы)); КонецЦикла; КонецЕсли; КонецЦикла; КонецЕсли; КонецЦикла;
ВыгрузитьПоказатель(элДокумента, "DATAF14",);
КонецЕсли; Иначе
//Если это не РегламентированныйОтчетФСС тогда // Данные, которые зависят от схемы СлужебнаяСтруктура.Вставить("C_DOC", Сред(ИмяСхемы,1,3)); СлужебнаяСтруктура.Вставить("C_DOC_SUB",Сред(ИмяСхемы,4,3)); СлужебнаяСтруктура.Вставить("C_DOC_VER",Число(Сред(ИмяСхемы,7,2))); СлужебнаяСтруктура.Вставить("SOFTWARE", "SOFTWARE");
// главный элемент DECLAR элДокумента = ДокЭкспорт.createElement("DECLAR"); ДокЭкспорт.appendChild(элДокумента);
Для Каждого СтрокаТела Из тбПоказателиТело Цикл Если СтрокаТела.Тип = "Таблица" Тогда ИмяНужнойГруппы = "";
тбПоказателиТаблицы = СтрокаТела.Таблица; Если Префикс = Неопределено Или Не ЗначениеЗаполнено(Префикс) Тогда ИмяНужнойГруппы = ПолучитьИзСтруктурыГруппы(тбПоказателиТаблицы[0].Имя); Иначе ИмяНужнойГруппы = ПолучитьИзСтруктурыГруппы(тбПоказателиТаблицы[0].Имя); ИмяНужнойГруппы = Префикс + ИмяНужнойГруппы; КонецЕсли;
//здесь будет получение из структуры "ДанныеМногостсрочных разделов" //строка тела соответствует таблице значений с элементами одной группы РеальныйИндСтроки = 1;
спСтроки = Новый СписокЗначений; Для ИндСтроки = 0 По СтруктураНужнойГруппы.Количество() - 1 Цикл // Максимально допустимое число строк
спЗначенияXML = Новый Соответствие; Для Каждого строка Из тбПоказателиТаблицы Цикл ИмяПоказателя = ИмяПоказателяВТаблице(строка.Имя,РеальныйИндСтроки); ИмяКолонки = СтрЗаменить(строка.Имя,"XXXX",""); Данные = СтруктураНужнойГруппы[ИндСтроки][ИмяКолонки]; ОписаниеОшибки = ""; ЗначениеXML = ПреобразоватьТипXML(Данные,строка.Тип,ИмяСхемы,ОписаниеОшибки); спЗначенияXML.Вставить(строка.Имя,ЗначениеXML); Если ЗначениеЗаполнено(ОписаниеОшибки) Тогда СтрокаОшибки = ТаблицаОшибок.Добавить(); СтрокаОшибки.ИмяТабличногоПоля = ИмяТабличногоПоля; СтрокаОшибки.ИмяПоказателя = ИмяПоказателя; СтрокаОшибки.ОписаниеОшибки = ОписаниеОшибки; КонецЕсли;
КонецЦикла;
Если СтарыйТипВыгрузки Тогда Для Инд = 0 По спЗначенияXML.Количество() - 1 Цикл ИмяПоказателя = тбПоказателиТаблицы[Инд].Имя; ЗначениеXML = спЗначенияXML[ИмяПоказателя]; ВыгрузитьПоказатель(элТело, ИмяПоказателя, ЗначениеXML, Новый Структура("ROWNUM", РеальныйИндСтроки)); КонецЦикла; РеальныйИндСтроки = РеальныйИндСтроки + 1; Иначе // Записываем в список спСтроки.Добавить(спЗначенияXML); РеальныйИндСтроки = РеальныйИндСтроки + 1; КонецЕсли; КонецЦикла;
Если НЕ СтарыйТипВыгрузки Тогда // Выгружаем Для Каждого Показатель Из тбПоказателиТаблицы Цикл ИмяПоказателя = Показатель.Имя; Для ИндС = 0 По спСтроки.Количество() - 1 Цикл спЗначенияXML = спСтроки[ИндС].Значение; // Выгружаем ЗначениеXML = спЗначенияXML[ИмяПоказателя]; ВыгрузитьПоказатель(элТело, ИмяПоказателя, ЗначениеXML, Новый Структура("ROWNUM",ИндС+1)); КонецЦикла; КонецЦикла; КонецЕсли; Иначе Если НЕ (ИмяСхемы = "R1201501" И СтрокаТела.Имя = "INN") Тогда
//<!--Загальний тип "Індивідуальний податковий номер "--> Если НЕ ЗначениеЗаполнено(Значение) Тогда Результат = 0; ИначеЕсли ТипЗнч(Значение)=Тип("Строка") Тогда Результат = СтрЗаменить(Значение, " ", ""); Результат = СтрЗаменить(Результат, ",", "."); ИначеЕсли ТипЗнч(Значение)=Тип("Число") Тогда Результат = Формат(Значение,"ЧДЦ=0; ЧГ=0"); Иначе Результат = СокрЛП(Строка(Значение)); КонецЕсли;
Попытка Контроль = Число(Результат); Если Найти(Результат, ".") > 0 ИЛИ Контроль < 1000 ИЛИ Контроль > 999999999999 ИЛИ Цел(Контроль) <> Контроль Тогда ОписаниеОшибки = "Значение не является целым числом от 1000 до 999999999999"; КонецЕсли; Исключение ОписаниеОшибки = "Значение не является целым числом от 1000 до 999999999999"; КонецПопытки;
// проверка аттрибутов Если НЕ ЗначениеЗаполнено(QDATE) ИЛИ НЕ ТипЗнч(QDATE) = Тип("Дата") Тогда СтрокаОшибки = ТаблицаОшибок.Добавить(); СтрокаОшибки.ИмяТабличногоПоля = "ПолеТабличногоДокументаНалоговыйДокумент"; СтрокаОшибки.ИмяПоказателя = "T1Z" + Формат(ROWNUM,"ЧЦ=4;ЧВН=0;ЧГ=;") + "QDATE"; СтрокаОшибки.ОписаниеОшибки = "Не заполнена дата"; КонецЕсли;
Если Не ЗначениеЗаполнено(QNUM) и НЕ ЗначениеЗаполнено(RNUM) Тогда СтрокаОшибки = ТаблицаОшибок.Добавить(); СтрокаОшибки.ИмяТабличногоПоля = "ПолеТабличногоДокументаНалоговыйДокумент"; СтрокаОшибки.ИмяПоказателя = "T1Z" + Формат(ROWNUM,"ЧЦ=4;ЧВН=0;ЧГ=;") + "QNUM"; СтрокаОшибки.ОписаниеОшибки = "Не указан ни номер налоговой накладной ни номер расчета корретировки"; КонецЕсли;
Error = ДокЭкспорт.parseError; Если Error.errorCode<>0 Тогда // есть ошибка фОшибка = 1; Сообщить(НСтр("ru = 'Ошибка:'; uk = 'Помилка:'")); Сообщить(Error.reason); КонецЕсли;
Группа: Местный
Сообщений: 2908
Из: Київ, Україна
Спасибо сказали: 1159 раз
Рейтинг: 1244.5
Надо в конфе сделать поиск по "Новый COMОбъект("Msxml2.DOMDocument" и смотреть. Смотрел по Бухгалтерии - не так уж и много. Методы и свойства в основном аналогичные. По поводу COMОбъект("Msxml2.XMLSchemaCache.4.0") ничего не скажу, т. к. не знаком с этим объектом, но в Бухгалтерии этот код закомментирован.
Допрацьовую: - "Бухгалтерія для України 2.1"; - "Альфа-Авто: Автосалон+Автосервіс+Автозапчастини, українська версія".
Группа: Пользователи
Сообщений: 96
Из: Кривой Рог, Украина
Спасибо сказали: 10 раз
Рейтинг: 0
Цитата(Petre @ 24.11.14, 16:12)
Надо в конфе сделать поиск по "Новый COMОбъект("Msxml2.DOMDocument" и смотреть. Смотрел по Бухгалтерии - не так уж и много. Методы и свойства в основном аналогичные. По поводу COMОбъект("Msxml2.XMLSchemaCache.4.0") ничего не скажу, т. к. не знаком с этим объектом, но в Бухгалтерии этот код закомментирован.
Попробую выдрать из бухгалтерии тогда, чтоль... Может там сделано уже без этого как-то внутренними методами, пока туда еще не вникал.
Группа: Основатель
Сообщений: 13981
Из: Киев
Спасибо сказали: 4549 раз
Рейтинг: 3678.1
Я бы вашу проблему попробовал решить на организационном уровне: объяснить директору, что для нормальной выгрузки налоговой отчетности нужен комп с Windows. А остальные пусть себе в Linux-е работают.
Группа: Пользователи
Сообщений: 96
Из: Кривой Рог, Украина
Спасибо сказали: 10 раз
Рейтинг: 0
Цитата(Vofka @ 24.11.14, 17:24)
Я бы вашу проблему попробовал решить на организационном уровне: объяснить директору, что для нормальной выгрузки налоговой отчетности нужен комп с Windows. А остальные пусть себе в Linux-е работают.
А директор пошлет меня куда подальше, потому что надо как минимум 7 лицензий купить...
Потому что никто к 1 компу бегать ради отчета не будет, а отчеты шлют точно 3 человека на первом офисе, и по 2 на втором и третьем, да и офисы минимум час езды в одну сторону друг от друга...
А решить проблему еще более круто - всех в 1 офис загнать, точно никто не согласится.
В общем при попытке добавить common_types.xsd как объект XDTO вылезла вот такая ошибка:
Цитата
Ошибка проверки модели XDTO: xdto-valueType-6.1 тип: DGpercentAlloc пакет: common_types Атомарная модель содержания не соответствует определению типа значения Ошибка проверки модели XDTO: xdto-valueType-6.1 тип: DGDateEndKv пакет: common_types Атомарная модель содержания не соответствует определению типа значения
Посмотрел - а там по сути тип и не указан... Что нужно выбрать и откуда как в поле тип для данных элементов? Схема если что вот - [необходимо зарегистрироваться для просмотра ссылки]
По сути пакет придется в полуручном режиме делать, так как требует небольших модификаций, но хоть типы сразу все готовые будут, вроде бы все получается и вывод считай 1 в 1 как должен быть, только вот зараза эти два типа не принимает и сохранять пакет не хочет
Разобрался, нужно было для DGDateEndKv указать тип из того же пакета DGDate, а для DGpercentAlloc указать тоже из того же пакета DGdecimal2. Все сохранилось нормально. Единственное теперь нужно разрулить структуру, например, для элемента T1RXXXXG1 нужно добавить два свойства: ROWNUM и __content, где в первый записывать номер строки, а во второй собственно говоря само значение.
Ну и читать колонки слева на право построчно (взял колонку, записал все строки), а не как по умолчанию - строку взял, все колонки записал и т.д.
Группа: Пользователи
Сообщений: 96
Из: Кривой Рог, Украина
Спасибо сказали: 10 раз
Рейтинг: 0
Итак, спустя неделю, я таки добился рабочего объекта XDTO. Он выглядит вот так - [необходимо зарегистрироваться для просмотра ссылки]. Сейчас доделаю код, который это все заполняет и так же выложу рядом. Что касается каких-либо изменений от налоговой и как их вносить:
Находим что изменилось в оригинальном xsd в сравнении с предыдущей версией
Измененные элементы находим и правим в нашем новом xsd
Меняем пространство имен в нашем новом xsd на правильное
Загружаем наш новый xsd в систему 1С
По надобности подправляем обработку вывода, правим элементы и т.д.
Теоретически должно быть универсально.
Да, уточню, данный xsd - это рабочий объект XDTO для схемы J1201507.xsd которая находится в архиве налоговой и актуальна на данный момент.
Группа: Пользователи
Сообщений: 96
Из: Кривой Рог, Украина
Спасибо сказали: 10 раз
Рейтинг: 0
В общем оказалось все не так-то просто =) Пришлось еще раз переделать XDTO, выходной XML придется еще подправлять дополнительно, хотя, может быть, когда допишу код и все выложу, меня кто-то поправит. К концу недели думаю получится полностью готовую обработку для реестра налоговых накладных.
Группа: Пользователи
Сообщений: 96
Из: Кривой Рог, Украина
Спасибо сказали: 10 раз
Рейтинг: 0
Проверил только что, окончательно рабочий объект XDTO для схемы J1201507.xsd, работает и готов к использованию (медок глотнул на ура), вот его [необходимо зарегистрироваться для просмотра ссылки]. В код осталось добавить только генерацию имени файла и обработку каждой строки из сформированного реестра.
1С Предприятие 8.3, 1С Предприятие 8.2, 1С Предприятие 8.1, 1С Предприятие 8.0, 1С Предприятие 7.7, Литература 1С, Общие вопросы по администрированию 1С, Методическая поддержка 1С - всё в одном месте: на Украинском 1С форуме!