PowerShell - Вывод элементов списка в виде массива

Аватара пользователя
YuS_2

Re: PowerShell - Вывод элементов списка в виде массива

Сообщение YuS_2 »

Да, совсем забыл:

код просто подкорректирован для наличия нескольких однотипных элементов в одном файле, но считать может пока неверно... т.е. его ещё надо проверять.
Аватара пользователя
NickM

Re: PowerShell - Вывод элементов списка в виде массива

Сообщение NickM »

Цитата YuS_2:



По новым примерам было, конечно, проще поправить код... но непонятно, как могут возникать различия при сверке, т.к. Вашим кодом они не обнаружены.
PowerShell - Вывод элементов списка в виде массива




Всё верно, т.к. в приложенных примерах расхождений не имеется, но как только у физ.лица изменить хоть какой-нибудь сравниваемый тег - ИНН, СНИЛС, сумму в любом месяце квартала в любой из форм, сразу выйдет расхождение;




Цитата YuS_2:



Вот видите, это пример того, что без внятного ТЗ, как правило и результат ХЗ
PowerShell - Вывод элементов списка в виде массива




Извините, полагал, что описание
PowerShell - Вывод элементов списка в виде массива
и комментарий в коде окажется достаточным Изображение



Скрытый текст

[spoiler]Цитата:[/spoiler]



ТЗ.

1. Получить табличное представление каждой из форм, где каждая строка представляет из себя:

ФИО, ИНН, СНИЛС, итоговая сумма за год, ежемесячная сумма за каждый месяц – [1], [2]…[12];



2. Произвести сверку двух форм, где различие составляют как перс.данные(ФИО, ИНН, СНИЛС), как итоговая сумма за год, так и суммы за каждый месяц;



Сверка форм осуществляется в разрезе квартала/ кварталов. Т.е. форм 1151162 всегда кратно 3 количества форм 1151111, т.е. если сверяем один квартал, тогда 1151162= 3шт., 1151111= 1шт., сверяем 2 квартала – 6шт. и 2 шт. соответственно (по сути, это не имеет значения, т.к. для проверки всегда подаётся правильное количество форм).



Некоторые замечания по формам:

В 1151111 могут отсутствовать сравниваемые теги с суммами в следующем узле, как и сам родительский узел: «СвВыплСВОПС»--> «СвВыпл»--> «СвВыплМК».












Цитата YuS_2:



но для доведения этого кода "до ума", необходимо таки уточнение многих моментов, которые было бы неплохо описать в виде:
PowerShell - Вывод элементов списка в виде массива




Опять же упомяну приложенный Мною рабочий код, который формирует как табличные данные, так и выполняет сверку;




Цитата YuS_2:



Основной скелет кода составлен
PowerShell - Вывод элементов списка в виде массива




Да, Вы показали как использовать процедуры/ функции в powershell и не только это, что возьму на вооружение/ непременно этим воспользуюсь.
Аватара пользователя
YuS_2

Re: PowerShell - Вывод элементов списка в виде массива

Сообщение YuS_2 »

Цитата NickM:



но как только у физ.лица изменить хоть какой-нибудь сравниваемый тег - ИНН, СНИЛС, сумму в любом месяце квартала в любой из форм, сразу выйдет расхождение
PowerShell - Вывод элементов списка в виде массива




Понятно, так и сделал... вылезли ещё баги... поправлены




Цитата NickM:



Извините, полагал, что описание в посте и комментарий в коде окажется достаточным
PowerShell - Вывод элементов списка в виде массива




Ну, номера форм для меня малоинформативны оказались... а код чужой разбирать... ну, это не очень продуктивно, учитывая, что автор кода мог иметь свой алгоритм для реализации задачи и по коду не всегда его можно легко определить.




Цитата NickM:



ТЗ.
PowerShell - Вывод элементов списка в виде массива




Так гораздо понятнее!



Примерно так:



Код:

Код: Выделить всё

# Функция получения кода документа и периода (месяц/квартал)
function Get-NodeAttrDoc ($xml,$node,$enc){
    process{
        $n = $xml.selectnodes("//$node")
        [pscustomobject]@{'КНД' = $n.кнд;'Период' = $n.период}
    }
}
# Функция формирования выходных данных
function Get-NodeDataOut ($xml,$node,$pnode,$per,$dat,$fio,$enc,$knd){
    process{
        $tarr = $xml.selectnodes("//$node")
        $out = foreach($t in $tarr){
            $s,$sv,$tsv = @(@([double]0)*13),@(@([double]0)*3),$null
            if($pnode){
                $f,$inn,$sni = $t.$pnode.$fio,$t.$pnode.иннфл,$t.$pnode.снилс
            } else {
                $f,$inn,$sni = $t.$fio,$t.иннфл,$t.снилс
            }
            if (($i=[int]$per) -lt 13){$s[$i] = [double]$t.сумвыпл} else {
                $tsv = $t.getelementsbytagname($dat)
                if ($tsv){
                    foreach($it in $tsv){
                        $sv[([int]$it.месяц-1)] = [double]$it.сумвыпл
                    }
                }
                switch ($per){
                    $kv[0]{$s[1]=$sv[0];$s[2]=$sv[1];$s[3]=$sv[2]}
                    $kv[1]{$s[4]=$sv[0];$s[5]=$sv[1];$s[6]=$sv[2]}
                    $kv[2]{$s[7]=$sv[0];$s[8]=$sv[1];$s[9]=$sv[2]}
                    $kv[3]{$s[10]=$sv[0];$s[11]=$sv[1];$s[12]=$sv[2]}
                }
                $s[0] = ($s|measure -sum).sum
            }
            [pscustomobject]@{
                'КНД' = $knd
                'ФИО' = ($f.фамилия,$f.имя,$f.отчество) -join ' '
                'ИННФЛ' = $inn
                'СНИЛС' = $sni
                'СумГод' = $s[0]
                '01' = $s[1]
                '02' = $s[2]
                '03' = $s[3]
                '04' = $s[4]
                '05' = $s[5]
                '06' = $s[6]
                '07' = $s[7]
                '08' = $s[8]
                '09' = $s[9]
                '10' = $s[10]
                '11' = $s[11]
                '12' = $s[12]
            }
        }
    }
    end{return $out}
}
# Функция суммирования отдельных документов на единое лицо
function get-sumdoc1162 ($elem,$i){
    $b = $i|%{($elem.$_|measure -sum).sum}
    [pscustomobject]@{
        'КНД' = $elem[0].кнд
        'ФИО' = $elem[0].фио
        'ИННФЛ' = $elem[0].иннфл
        'СНИЛС' = $elem[0].снилс
        'СумГод' = ($b|measure -sum).sum
        '01' = $b[0]
        '02' = $b[1]
        '03' = $b[2]
        '04' = $b[3]
        '05' = $b[4]
        '06' = $b[5]
        '07' = $b[6]
        '08' = $b[7]
        '09' = $b[8]
        '10' = $b[9]
        '11' = $b[10]
        '12' = $b[11]
    }
}
# Инициализация переменных и сплаттинг
$path = "$psscriptroot\xml"
if ($host.version.major -gt 5) {
    $enc = 'windows-1251'
    $csv = @{
        Encoding = 'utf8'
        NoTypeInformation = $true
        UseQuotes = 'AsNeed'
    }
} else {
    $enc = 'default'
    $csv = @{
        Encoding = 'utf8'
        NoTypeInformation = $true
    }
}
$flt = 'NO_*.xml'
$nd = 'Документ'
$nd_pssl = 'ПерсСвСтрахЛиц'
$nd_dfl = 'ДанФЛПолуч'
$nd_svmk = 'СвВыплМК'
$nd_psfl = 'ПерсСвФЛ'
$fio = 'ФИО'
$kv = @('21','31','33','34') 
$arr1162_i, $arr1111 = @(),@()
# Основной код
dir $path -filt $flt -file|%{
    $x = [xml](gc $_.fullname -enc $enc)
    $tmp = get-nodeattrdoc $x $nd $enc
    $knd = $tmp.кнд
    $per = $tmp.период
    $ndo = @{XML=$x;PER=$per;FIO=$fio;ENC=$enc;KND=$knd}
    if ($knd -eq '1151111'){
        $arr1111 += get-nodedataout @ndo -node $nd_pssl -pnode $nd_dfl -d $nd_svmk
    } else {
        $arr1162_i += get-nodedataout @ndo -node $nd_psfl
    }
}
#Получаем список кодов периодов помесячно:
$m = 1.. 12|%{"$_".padleft(2,'0')}
# Суммируем помесячные документы на одно лицо (единый ИННФЛ) в единую строку:
$arr1162 = $arr1162_i|group -prop 'иннфл'|%{get-sumdoc1162 $_.group $m}
# Экспорт в CSV файлы 
$arr1162|sort 'ФИО'|export-csv '1162.csv' @csv
$arr1111|sort 'ФИО'|export-csv '1111.csv' @csv
# Вывод в консоль общей таблицы:
$arr1111+$arr1162|sort 'ФИО','КНД'|ft * -a -w
# Получение различий с индикаторами:
diff $arr1111 $arr1162 -prop "ФИО","ИННФЛ",'СумГод','01','02',
'03','04','05','06','07','08','09','10','11','12'|export-csv 'diff.csv' @csv

- подробно комментировать не стал, просто обозначил где что расположено.

Формируются два выходных файла с данными в CSV формате, плюс CSV-файл с различиями в данных, если таковые обнаружатся - файл хоть и один, но у каждой строки будет индикатор из какого массива получены данные: "" - DifferenceObject
Аватара пользователя
YuS_2

Re: PowerShell - Вывод элементов списка в виде массива

Сообщение YuS_2 »

Цитата YuS_2:



- подробно комментировать не стал, просто обозначил где что расположено.
PowerShell - Вывод элементов списка в виде массива




Благодарю, код полностью читаем и понятен.



На выборочных данных работает в среднем на 100-150 миллисекунд быстрее (проверку СНИЛС в diff добавить не составило труда Изображение ).
Аватара пользователя
YuS_2

Re: PowerShell - Вывод элементов списка в виде массива

Сообщение YuS_2 »

NickM, а, да, забыл совсем... есть ещё более наглядная визуализация табличных данных.

Замените код здесь:



Код:

Код: Выделить всё

$arr1111+$arr1162|sort 'ФИО','КНД'|ft * -a -w

на такой:



Код:

Код: Выделить всё

$arr1111+$arr1162|sort 'ФИО','КНД'|ogv
Аватара пользователя
NickM

Re: PowerShell - Вывод элементов списка в виде массива

Сообщение NickM »

Цитата YuS_2:



есть ещё более наглядная визуализация табличных данных.
PowerShell - Вывод элементов списка в виде массива




Ага, отображение в гриде.



Спаcибо, но достаточно *.csv для табличного редактора "Excel".
Ответить

Вернуться в «Скриптовые языки администрирования Windows»