Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   [решено] Сопоставление сотрудников из 1С учетным записям в AD (http://forum.oszone.net/showthread.php?t=276615)

IvanXXL 28-01-2014 11:32 2297745

Сопоставление сотрудников из 1С учетным записям в AD
 
Прошу помочь по возможности в решении задачи:

Есть csv-выгрузка из 1С такого вида:
Код:

Фамилия;Имя;Отчество;ТН;ДР;СНИЛС;Организация;Подразделение;Должность;Дата приема;Дата увольнения
Пупкин;Василий;Алибабаевич;0009876543;19.02.1966;888-777-666 55;ООО "Рога и копыта";Бухгалтерия;шредерщик;08.07.2000

и есть учетные записи в AD с displayname вида "Василий А. Пупкин".
Учитывая, что в домене отчество обозначено только первым символом, а в выгрузке полностью, то возможны совпадения при сравнении, т.к. в выгрузке есть еще , например, сотрудник "Пупкин Василий Алексеевич".
Необходимо очистить выгрузку от неуникальных в этом отношении записей, т.е. в данном случае удалить обоих Пупкиных, и дополнить очищенную выгрузку графой "samaccountname", заполнив ее соответствующими данными из AD (если есть).
Все учетные записи в AD находятся в OU Domain\Сотрудники. CSV в win-кодировке.

Iska 28-01-2014 12:28 2297776

Цитата:

Цитата IvanXXL
Учитывая, что в домене отчество обозначено только первым символом, »

Просто при создании пользователей администратор был ленив, чтобы вводить составляющую «О» (из ФИО) в «Выводимое имя» полностью.

IvanXXL 28-01-2014 13:45 2297821

Цитата:

Цитата Iska
Просто при создании пользователей администратор был ленив, чтобы вводить составляющую «О» (из ФИО) в «Выводимое имя» полностью. »

История умалчивает, почему админы в учетных записях не забивали отчество полностью, однако учетных записей уже более 2000, а порядок навести надо бы.

Iska 28-01-2014 14:09 2297836

IvanXXL, рано или поздно отчество придётся вносить полностью.

IvanXXL 28-01-2014 14:51 2297864

Цитата:

Цитата Iska
рано или поздно отчество придётся вносить полностью. »

Так ведь поэтому и попросил помощи, если хотя бы половину удастся сопоставить, то я кучу времени сэкономлю.
А если по существу, то вы лично можете мне помочь в решении сформулированной задачи?

Kazun 28-01-2014 15:05 2297874

ТН;ДР;СНИЛС;Организация;Подразделение;Должность;Дата приема;Дата увольнения - Атрибуты в AD требуется угадать, если есть дублирующие записи?

Подразделение;Должность - Присутствуют в AD?

IvanXXL 28-01-2014 15:37 2297901

Текущая структура в AD - это свалка, которую еще мне предстоит разгрести. Там привязаться не к чему. Выводимое имя - это единственное, чему можно сейчас доверять. Поэтому дубли имен из выгрузки надо отбрасывать. Их надо будет вручную выверять. Поля выгрузки, кроме имени, отчества и фамилии, в решении текущей задачи использовать не предполагалось, они потребуются впоследствии для актуализации информации в AD после сопоставления сотрудников с учетными записями.

Kazun 28-01-2014 16:07 2297934

Код:

$result = Import-Csv users.csv -Delimiter ";" |
        Group {"{0} {1} {2}" -f $_.Имя,$_.Отчество[0],$_.Фамилия} | Where {$_.Count -eq 1} | Foreach {
                $name = $_.Name
                $sam = (Get-ADUser -Filter "DisplayName -eq '$name'").SamAccountName
                if(Get-ADUser -Filter "DisplayName -eq '$name'") {
                        $_.Group | Add-Member -NotePropertyName SamAccountName -NotePropertyValue $sam -PassThru
                }
                else {
                        $_.Group | Add-Member -NotePropertyName SamAccountName -NotePropertyValue "" -PassThru
                }
        }


IvanXXL 29-01-2014 07:11 2298294

Kazun, если не сложно, то прошу прокомментировать работу кода, в частности мне непонятна строка "$name = $_.Name".

Kazun 29-01-2014 09:18 2298319

1) Import-Csv users.csv -Delimiter ";" - Импортируем данные из CSV
2) Далее передаем по конвейеру командлету Group-Object, для поиска объектов, которые получаются одинаковые при приведении к виду Василий А Пупкин(если требуется Василий А. Пупкин - то изменить на "{0} {1}. {2}").

Код:

PS > Import-Csv users.csv -Delimiter ";" | Group {"{0} {1}. {2}" -f $_.Имя,$_.Отчество[0],$_.Фамилия}

Count Name                      Group
----- ----                      -----
    2 Василий А. Пупкин        {@{Фамилия=Пупкин; Имя=Василий; Отчество=Алибабаевич; ТН=0009876543; ДР=19.02.1966
    1 Адексааа А. Бульба        {@{Фамилия=Бульба; Имя=Адексааа; Отчество=Алибабаевич; ТН=0009876543; ДР=19.02.1966

3) Далее передаем по конвейеру и фильтруем уникальные элементы.
Код:

PS Import-Csv 1.csv -Delimiter ";" | Group {"{0} {1}. {2}" -f $_.Имя,$_.Отчество[0],$_.Фамилия} | Where{ $_.Count -eq 1}

Count Name                      Group
----- ----                      -----
    1 Адексааа А. Бульба        {@{Фамилия=Бульба; Имя=Адексааа; Отчество=Алибабаевич; ТН=0009876543; ДР=19.02.1966;...

4) $name = $_.Name - Будет содержать Адексааа А. Бульба(текущий элемент в конвейере)
5) $sam = (Get-ADUser -Filter "DisplayName -eq '$name'").SamAccountName - Производим поиск в AD и пробуем получить свойство SamAccountName
6) Дальше, случайно , добавил лишнюю проверку. if(Get-ADUser -Filter "DisplayName -eq '$name'") - Достаточно if($sam)
7) $_.Group | Add-Member -NotePropertyName SamAccountName -NotePropertyValue $sam -PassThru - Добавляем новое свойство к объекту

Код:

$result = Import-Csv users.csv -Delimiter ";" |
        Group {"{0} {1}. {2}" -f $_.Имя,$_.Отчество[0],$_.Фамилия} | Where {$_.Count -eq 1} | Foreach {
                $name = $_.Name
                $sam = (Get-ADUser -Filter "DisplayName -eq '$name'").SamAccountName
                if($sam) {
                        $_.Group | Add-Member -NotePropertyName SamAccountName -NotePropertyValue $sam -PassThru
                }
                else {
                        $_.Group | Add-Member -NotePropertyName SamAccountName -NotePropertyValue "" -PassThru
                }
        }

Код:

PS > $result

Фамилия        : Иванов
Имя            : Иван
Отчество        : Иванович
ТН              : 0009876543
ДР              : 19.02.1966
СНИЛС          : 888-777-666 55
Организация    : ООО "Рога и копыта"
Подразделение  : Бухгалтерия
Должность      : шредерщик
Дата приема    : 08.07.2000
Дата увольнения :
SamAccountName  : iivanov


IvanXXL 29-01-2014 09:36 2298326

Kazun, спасибо за подробные комментарии.
Но возникла одна проблема: на контроллере домена не установлены веб-службы AD. Возможно заменить командлет Get-ADUser на Get-QADUser?

Kazun 29-01-2014 09:38 2298328

Конечно возможно:
Код:

(Get-QADUser -DisplayName $name).SamAccountName

IvanXXL 29-01-2014 11:01 2298366

Kazun, спасибо за подсказку.

Я отказался от русских имен в заголовках:
было
Фамилия;Имя;Отчество;ТН;ДР;СНИЛС;Организация;Подразделение;Должность;Дата приема;Дата увольнения
стало
LastName;Name1;Name2;ID;Birthday;SNILS;Organization;Department;Role;Employment;Dismissal

Выполняю вот такой скрипт:
Код:

cls
$path="d:\_ps\1s-AD"
$result = Import-Csv $path\users.csv -Delimiter ";" |
        Group {"{0} {1} {2}" -f $_.Name1,$_.Name2[0],$_.LastName} | Where {$_.Count -eq 1} | Foreach {
                $name = $_.Name               
                $sam = (Get-QADUser -DisplayName $name).SamAccountName
                if($sam) {
                        $_.Group | Add-Member -NotePropertyName SamAccountName -NotePropertyValue $sam -PassThru
                }
                else {
                        $_.Group | Add-Member -NotePropertyName SamAccountName -NotePropertyValue "" -PassThru
                }
        }
$result|export-csv $path\filtered-users.csv -Delimiter ";" -Encoding Default

Получаю такие сообщения об ошибках:
Код:

Add-Member : Не удается найти параметр, соответствующий имени параметра "NotePropertyName".
D:\_ps\1s-AD\0.ps1:11 знак:43
+            $_.Group | Add-Member -NotePropertyName <<<<  SamAccountName -NotePropertyValue "" -PassThru
    + CategoryInfo          : InvalidArgument: (:) [Add-Member], ParameterBindingException
    + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.AddMemberCommand
 
Export-Csv : Не удается привязать аргумента к параметру "InputObject", так как он имеет значение NULL.
D:\_ps\1s-AD\0.ps1:14 знак:19
+ $result|export-csv <<<<  $path\filtered-users.csv -Delimiter ";" -Encoding Default
    + CategoryInfo          : InvalidData: (:) [Export-Csv], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ExportCsvCommand

Что не так?

Kazun 29-01-2014 11:05 2298368

Использовал версию V3,для V2:
Код:

$_.Group | Add-Member -MemberType NoteProperty -Name SamAccountName -Value $sam -PassThru

IvanXXL 29-01-2014 11:32 2298381

Kazun,
Не успеваю за прогрессом! :)

А по существу: огромное спасибо за помощь! Небольшое дополнение: для корректного поиска нужна была точка после инициала отчества тут:
Код:

Group {"{0} {1}. {2}" -f $_.Name1,$_.Name2[0],$_.LastName} | Where {$_.Count -eq 1} | Foreach {
Вопрос решен - тему можно считать закрытой.

Итоговый скрипт:
Код:

cls
$path="d:\_ps\1s-AD"
$result = Import-Csv $path\users.csv -Delimiter ";" |
    Group {"{0} {1}. {2}" -f $_.Name1,$_.Name2[0],$_.LastName} | Where {$_.Count -eq 1} | Foreach {
        $name = $_.Name       
        $sam = (Get-QADUser -DisplayName $name).SamAccountName
        if($sam) {
            $_.Group | Add-Member -MemberType NoteProperty -Name SamAccountName -Value $sam -PassThru
        }
        else {
            $_.Group | Add-Member -MemberType NoteProperty -Name SamAccountName -Value "" -PassThru
        }
    }
$result|export-csv $path\filtered-users.csv -Delimiter ";" -Encoding Default


IvanXXL 30-01-2014 09:36 2299023

Kazun, еще раз спасибо за помощь в решении.
Но если не сложно, то, так сказать "для расширения кругозора" подскажи, как выглядел бы скрипт, если бы не требовалось очищать выгрузку от неуникальных записей "Имя О. Фамилия", но поиск в AD осуществлялся бы только для уникальных записей "Имя О. Фамилия"?

Kazun 30-01-2014 09:41 2299025

Код:

Group {"{0} {1}. {2}" -f $_.Name1,$_.Name2[0],$_.LastName} | Foreach {
                if($_.Count -eq 1) {
                        $name = $_.Name       
                        $sam = (Get-QADUser -DisplayName $name).SamAccountName
                        if($sam) {
                                $_.Group | Add-Member -MemberType NoteProperty -Name SamAccountName -Value $sam -PassThru
                        }
                        else {
                                $_.Group | Add-Member -MemberType NoteProperty -Name SamAccountName -Value "" -PassThru
                        }
                }
                else {
                        $_.Group | Add-Member -MemberType NoteProperty -Name SamAccountName -Value "неуникальный" -PassThru
                }
    }


IvanXXL 31-01-2014 08:49 2299680

Kazun, ну и последний гипотетический вопрос: как можно организовать поэтапную работу скрипта, на каждом этапе обрабатывая записи с фамилиями только на одну букву (А, Б, В...) из единого файл-источника?

Kazun 31-01-2014 09:06 2299684

Делайте двойное группирование.
Код:

$data  = Import-Csv $path\users.csv -Delimiter ";"
$al = $data | Group {$_.LastName[0]} | Sort Name


IvanXXL 31-01-2014 09:27 2299691

Kazun,
Цитата:

Цитата Kazun
Делайте двойное группирование. »

Можно немного поподробнее? Я не понял, как это реализуется.

Kazun 31-01-2014 11:07 2299743

Код:

PS > $al

Count Name                      Group
----- ----                      -----
    1 Б                        {@{Фамилия=Бульба; Имя=Адексааа; Отчество=Алибаба
    1 К                        {@{Фамилия=Крендельков; Имя=Адексааа; Отчество=Ал
    2 П                        {@{Фамилия=Пупкин; Имя=Василий; Отчество=Алибабае

Теперь мне нужно все на букву K:
Код:

$k = $al | Where {$_.Name -eq "К"} | Foreach {$_.Group}

Код:

$result = $k |
    Group {"{0} {1}. {2}" -f $_.Name1,$_.Name2[0],$_.LastName} .......


IvanXXL 31-01-2014 11:16 2299748

Kazun, спасибо! Теперь доходчиво получилось! :)


Время: 05:17.

Время: 05:17.
© OSzone.net 2001-