Получить данные их XLSX файла без установки Microsoft Office
Если вы хотите или не можете установить Excel на компьютере ( например у вас отсутствуют лицензии для активации Office или в случае с Windows Server Core), вы можете использовать кроссплатформенный PowerShell модуль ImportExcel для работы с Excel документами.
Установите модуль из PowerShell Gallery:
Рассмотрим типовые операции с книгами Excel, которые можно выполнить с помощью этого модуля.
Экспорт данных в XLSX файл:
Изменить значение в ячейке Excel:
С помощью PSObject можно добавить данные в таблицу Excel:
$FilePath = "C:\ps\ad_users.xlsx" $ExcelData = Import-Excel -Path $FilePath -WorksheetName "AD_User_List" $NewUser = [PSCustomObject]@{ "UserName" = "aivanov" "FullName" = "Иванов Андрей" "Job" = "Инженер" } $ExcelData += $NewUser Export-Excel -Path $FilePath -WorksheetName "AD_User_List" -InputObject $ExcelData
Как работать?
Я не буду рассказывать, как установить IM, просто оставлю ссылку. Ближе к низу страницы под надписью Windows Binary Release. Устанавливается просто из exe файла. После установки IM становится доступен как команда Powershell или командной строки, с чего мы и начнем.
Первое что нужно отметить – писать сразу в 1С – не удобно. Куда проще сделать скрипт в PS, а потом уже перенести его в 1С. Для задач начальной разработки отлично подходит Powershell ISE: Нужно лишь создать файл .ps1. К слову, ISE решает каким-то образом и другую проблему обычного Powershell – кириллицу. Я не суперуверенный пользователь Powershell и у меня русскоязычный Windows Server, поэтому первое столкновение с “powershellexe завершил свою работу” при вводе пути до картинки с кириллическими символами, вызвало у меня фрустрацию. Возможно у вас таких проблем с кодировкой не будет (или вы знаете, как их решить), но если нет, то ISE – ваш лучший друг.
Команды (командлеты) PowerShell
В языке программы PowerShell команды носят название командлеты (от английского «cmdlet»). Все они формируются с использованием шаблона «Глагол-Существительное», или «Действие-Объект». Например, Get-Services
и Start-Process
. Благодаря такой структуре, можно легко понять предназначение команды, даже если вы с ней ещё не работали ранее.
Синтаксис командлетов
После имени самого командлета следует указание параметров и их значений. Между всеми частями команды следует проставлять пробелы. Вот пример синтаксиса командлета, который позволяет перейти в директорию C:\
:
Set-Location -LiteralPath C:\ -PassThru
Разберем его на составные части:
Set-Location
— буквально «вызвать команду». Этот командлет позволяет выполнять указанный блок сценария.-LiteralPath C:\
— здесь передаем блок сценария, в котором используется командаSet-Location
для перехода в каталогC:\
.-PassThru
— по умолчанию командлетInvoke-Command
не возвращает результат выполнения. Этот параметр указывает на необходимость вывода информации о местоположении, в которое был выполнен переход с помощью командыSet-Location
.

Важно отметить, что регистр букв в командах PowerShell не имеет значения. Таким образом, данную команду можно записать в виде заглавных букв, строчных букв или даже смешанного регистра, и она все равно будет выполняться:
sEt-loCATion -PATH c:\ -passthru
Когда в одной строке объединены несколько команд, они разделяются точкой с запятой
.;
Иногда команда может быть слишком длинной. Для разделения на несколько строк можно использовать символ обратного апострофа `
в месте переноса. Новую строку можно создать, нажав Shift + Enter (для переноса строки ниже текущей) или Ctrl + Enter (для переноса строки выше текущей).
Разделим предыдущую команду:
Set-Location ` -LiteralPath C:\ ` -PassThru

Алиасы
В процессе работы с терминалом иногда может быть неудобно постоянно вводить полные названия командлетов. Именно поэтому у наиболее часто используемых командлетов существуют псевдонимы (алиасы) — их сокращенные варианты.
Чтобы получить список доступных алиасов, вы можете воспользоваться командой Get-Alias
. Кроме того, данной команде также доступен псевдоним gal
.

Чтобы получить список алиасов для конкретного командлета, вы можете использовать параметр -Definition
. Пример:
Get-Alias -Definition Set-Location

Если вам нужно узнать полное название командлета по его алиасу, используйте параметр -Name
. Этот параметр необязателен, так как он является аргументом по умолчанию.
# Оба следующих варианта эквивалентны: Get-Alias -Name clear Get-Alias clear

Особенности обработки путей к каталогам
Для многих командлетов необходимо предоставить путь к файлу или каталогу. Это делается с использованием строки, например: C:\Windows\System32
.
Однако, если в пути встречается пробел или другой специальный символ, PowerShell будет рассматривать его как разделитель. Например:
# Следующая команда не будет выполнена корректно Set-Location C:\Program Files

PowerShell «воспринимает» пробел и интерпретирует его так, будто путь к папке закончился на слове Program
, а files
— это уже значение другого параметра.
Чтобы избежать подобных ситуаций, существует два метода:
- Экранировать символы с помощью обратного апострофа
`
:C:\Program` Files
. Однако это может быть неудобным, если путь длинный. - Поместить весь путь в одинарные или двойные кавычки:
'C:\Program Files'
или"C:\Program Files"
(желательнее использовать одинарные кавычки).
Кроме того, в PowerShell существуют сокращения для быстрого доступа к ближайшим директориям:
- Точка
.
указывает на текущий каталог. Например,Get-ChildItem .
позволяет просмотреть содержимое текущего местоположения. - Две точки
..
указывают на родительский каталог. Например,Set-Location ..
позволяет перейти к родительскому каталогу. Это может быть полезно, если вы находитесь в глубоко вложенной директории.
Большинство командлетов имеют параметры -Path
и -LiteralPath
, позволяющие указать путь к файлу или папке. Разница между ними заключается в том, что в -Path
можно включать переменные, в то время как —LiteralPath
интерпретирует символы буквально, даже если они содержат имя переменной.
Get-Help: как изучать новые командлеты
Для получения подробной информации о конкретном командлете воспользуйтесь командой Get-Help Название-Командлета
. Пример:
Get-Help Get-Childitem

У команды Get-Help
имеется несколько полезных параметров:
-Detailed
предоставляет более подробную справку по командлету.-Full
предоставляет полную справку.-Examples
демонстрирует примеры использования командлета.-Online
перенаправляет пользователя на веб-страницу с соответствующей документацией.
Чем PowerShell отличается от cmd
Рассмотрим сравнение двух основных инструментов командной строки в операционной системе Windows: PowerShell и командной строки (cmd). Оба инструмента позволяют взаимодействовать с операционной системой через команды и сценарии, однако они существенно различаются по своим характеристикам и функциональности.
Аспект | PowerShell | Командная строка (cmd) |
---|---|---|
Язык сценариев | Мощный язык на основе .NET Framework | Ограниченный язык для выполнения команд |
Объектная модель | Работа с объектами и конвейерная обработка | Работа с текстовыми строками и потоками |
Управление системой | Обширный набор командлетов для управления | Ограниченный набор команд для управления |
Синтаксис | Современный и читаемый синтаксис | Простой синтаксис команд и аргументов |
Поддержка модулей | Поддержка модулей для организации функциональности | Отсутствие концепции модулей |
Логические операторы
В PowerShell вы также можете выполнять арифметические операции над объектами и строками, сравнивать их друг с другом, используя логические операторы.
+
— сложение;-
— вычитание;*
— умножение;/
— деление;%
— деление по модулю;(
и)
— скобки для группировки операций.
Операторы сравнения оформляются так же, как параметры командлетов, и их названия произошли от английских выражений, указанных в скобках:
-eq
— равно (от «equal»);-ne
— не равно (от «not equal»);-gt
— больше (от «greater than»);-ge
— больше либо равно (от «greater than or equal»);-lt
— меньше (от «less than»);-le
— меньше либо равно (от «less than or equal»).
Для чего нужен PowerShell
PowerShell — это мощный инструмент для автоматизации задач, управления операционной системой и взаимодействия с различными приложениями и сервисами. Он широко используется администраторами систем, разработчиками, а также специалистами в области IT для решения разнообразных задач. Вот некоторые из основных применений PowerShell:
- Автоматизация задач: PowerShell позволяет создавать сценарии (скрипты) для автоматизации повторяющихся и рутинных задач, таких как установка программ, настройка системных параметров, копирование файлов и многие другие операции.
- Управление системой: PowerShell предоставляет доступ к широкому спектру системных функций, позволяя администраторам управлять пользователями, группами, службами, процессами, реестром и другими системными ресурсами.
- Конфигурация и развертывание: С помощью PowerShell можно создавать и применять конфигурации для развертывания и управления серверами и компьютерами, что делает процесс управления парком устройств более эффективным.
- Мониторинг и анализ: PowerShell позволяет анализировать системные данные, собирать статистику, мониторить производительность и события, что помогает администраторам быстро реагировать на проблемы.
- Взаимодействие с внешними приложениями и службами: PowerShell может взаимодействовать с другими приложениями и службами, используя API, веб-службы, REST API и другие протоколы, что позволяет автоматизировать процессы, связанные с сторонними приложениями.
- Разработка и тестирование: Разработчики используют PowerShell для создания сценариев тестирования, сборки проектов, управления версиями и других задач, связанных с разработкой ПО.
- Обработка данных: PowerShell предоставляет мощные инструменты для обработки и анализа данных, таких как текстовые файлы, CSV, XML и другие форматы данных.
- Безопасность: PowerShell может использоваться для управления политиками безопасности, мониторинга событий безопасности, а также для проведения аудитов безопасности системы.
Как открыть PowerShell в Windows
Как правило, PowerShell уже установлен на вашем компьютере по умолчанию. Однако, если по какой-то причине его нет, вы можете воспользоваться инструкциями, предоставленными Microsoft. В дополнение, в официальной документации имеются подробные руководства по установке на macOS и Linux.
PowerShell является независимым от версии операционной системы инструментом и работает одинаково стабильно как на Windows 10, так и на Windows Server.
Существует два основных метода для запуска PowerShell или PowerShell ISE в системе Windows: через меню «Пуск» и с помощью приложения «Выполнить».
- Для того чтобы открыть PowerShell через меню «Пуск», пройдите к папке Windows PowerShell, откройте её и выберите необходимое приложение. В этой директории доступны как 32-разрядные версии (отмечены как x86 в скобках), так и 64-разрядные версии терминала и ISE.

- Чтобы запустить PowerShell через приложение «Выполнить», используйте комбинацию клавиш Win + R. Когда появится окно, введите
powershell
илиpowershell ise
(в зависимости от того, какое приложение вам нужно) и нажмите кнопку ОК.

Где может пригодиться IM?
В любом месте, где одни однотипные картинки нужно превращать в другие однотипные картинки. Например:
– Накладывать водяные знаки
– Делать что-нибудь черно-белым
– Делать из одной картинки несколько, но в разных размерах
– Сделать машину по производству смешных картинок для канала в Телеграм
Последнее, конечно же, шутка
На самом деле, те примеры, которые я буду приводить дальше – это часть pet-проекта собственной системы управления контентом для группы ВК и Телеграм канала, которая зашла слишком далеко. Едва ли вам понадобится нечто подобное, но вариации команд, описанные там, без проблем покроют операции работы с картинками из карточек номенклатуры, например.
Задача 6
Запустить все файлы в папке оказалось легко средствами PowerShell. Как я уже упоминал ранее, запускаем его от имени администратора в папке, где лежит output от задачи 5. У меня это c:\speech_sense\upload_data\calls\powershell\
Set-ExecutionPolicy RemoteSigned
Get-ChildItem -Path . -Filter "*.ps1" | ForEach-Object { powershell -File $_.FullName }
Все файлы подгрузились примерно за ночь. Стоимость обработки составила примерно рубль на один фрагмент. В проекте с аудиофайлами перед загрузкой необходимо создать тег, в котором ищем фразы поздравления с праздником. Обязательно перед загрузкой файлов. Новые и отредактированные теги на уже загруженные файлы не работают. Хотите новый тег создать и посмотреть, где он встречается – грузите и платите за расшифровку заново.
Установив фильтр на этот тег для высказываний оператора, получается список аудиозаписей и их ID, в которых есть поздравление с праздником.
Работа со строками в PowerShell
PowerShell — мощный инструмент для автоматизации задач на платформе Windows. Работа со строками играет важную роль при обработке текстовых данных. Вот некоторые ключевые аспекты:
- Объединение строк: Чтобы объединить строки, используйте оператор
+
или метод.Concat()
. Пример:
$firstString = "Привет, " $secondString = "мир!" $combinedString = $firstString + $secondString
- Форматирование строк: Используйте оператор
-f
или метод.Format()
для вставки значений в строку. Пример:
$name = "Alice" $age = 30 $formattedString = "Привет, меня зовут {0} и мне {1} лет." -f $name, $age
- Интерполяция строк: С помощью символа
$
и фигурных скобок{}
можно вставлять значения переменных в строки. Пример:
$city = "Москва" $interpolatedString = "Я живу в городе $($city)."
- Разделение строк: Метод
.Split()
используется для разделения строки на подстроки. Пример:
$text = "яблоко,груша,банан" $fruits = $text.Split(",")
- Замена подстрок: С помощью метода
.Replace()
можно заменить подстроку в строке. Пример:
$text = "Привет, мир!" $modifiedText = $text.Replace("мир", "вселенная")
- Обрезка строк: Методы
.Trim()
,.TrimStart()
и.TrimEnd()
удаляют пробелы и другие символы в начале и конце строки.
Примеры использования методов для обрезки строк в PowerShell:
# Обрезка пробелов в начале и конце строки $rawString = " Пример строки с пробелами " $trimmedString = $rawString.Trim() Write-Host "Исходная строка: '$rawString'" Write-Host "Обрезанная строка: '$trimmedString'" # Обрезка только в начале строки $leftTrimmedString = $rawString.TrimStart() Write-Host "Строка после обрезки в начале: '$leftTrimmedString'" # Обрезка только в конце строки $rightTrimmedString = $rawString.TrimEnd() Write-Host "Строка после обрезки в конце: '$rightTrimmedString'"
При выполнении этого кода в консоли PowerShell вы увидите следующий вывод:
Исходная строка: ' Пример строки с пробелами '
Обрезанная строка: 'Пример строки с пробелами'
Строка после обрезки в начале: 'Пример строки с пробелами '
Строка после обрезки в конце: ' Пример строки с пробелами'
В данном примере видно, как методы .Trim()
, .TrimStart()
и .TrimEnd()
удаляют пробелы в начале и конце строки, соответственно.
Доступ к данным в файле Excel из PowerShell
Рассмотрим на простом примере как получить доступ из PowerShell к данным в Excel файле со списком сотрудников.
Запустите приложение Excel (Application layer), создав COM объект:
Чтобы создать этот COM объект, Excel должен быть установлен на компьютере.
Эта команда запустите в фоновом режиме приложение Excel. Чтобы сделать окно Excel видимым, нужно изменить свойство Visible COM объекта:
Вывести все свойства объекта Excel:
Теперь можно открыть файл Excel (книгу, workbook):
В каждом файле Excel может быть несколько листов (worksheets). Вывести список листов в текущей книге Excel:
Теперь можно открыть конкретный лист (по его имени или индексу):<
Текущий (активный) лист Excel можно узнать командой:
Для получения значения из ячейки Excel нужно указать ее номер. Теперь вы можете получить значения из ячеек документа Excel. Можно использовать различные способы адресации ячеек в книге Excel: через диапазон (Range), ячейку (Cell), столбец (Columns) или строку (Rows). Ниже показаны примеры получения данных из одной и той же ячейки:
Переменные
Для сохранения данных и обращения к ним в будущем в PowerShell используются переменные. Перед названием переменной ставится символ доллара $
, и переменные могут содержать латинские буквы (как заглавные, так и строчные), цифры и символ нижнего подчеркивания.
Переменные в могут хранить данные различных типов, и значения в них можно изменять (перезаписывать).

Создадим переменную со строкой 2023
и преобразуем её в число. Для того чтобы узнать тип данных, воспользуемся методом .GetType()
:
$stringValue = "2023" $intValue = [int]$stringValue $intValue.GetType()

Для удаления переменной используется метод .Clear()
.
Переменные можно вставлять в строки, если строки оформлены двойными кавычками. В случае одинарных кавычек, PowerShell воспринимает символы в строке буквально. Давайте сравним два примера:
$number = 42 Write-Host "The number is $number" # Вывод: The number is 42 Write-Host 'The number is $number' # Вывод: The number is $number
В первом случае, используя двойные кавычки, значение переменной $number
подставляется в строку. Во втором случае, с использованием одинарных кавычек, строка остается буквальной, и $number
не интерпретируется как переменная.
Кроме пользовательских переменных, существуют и системные переменные. Например, $PSVersionTable
содержит информацию о версии PowerShell.

Очистка журнал событий из графической консоли Event Viewer
Самый интуитивный способ очистки журналов событий Windows – воспользоваться графической консоль Event Viewer.
- Запустите консоль
eventvwr.msc
; - Щелкните правой кнопкой по журналу и выберите Clear Log;
Такой способ позволяет быстро удалить все события из одного конкретного журнала. Однако в Windows используется несколько сотен журналов для разных компонентов операционной системы и стороннего ПО.
По умолчанию Windows хранит журналы в файлах с расширением EVTX в каталоге
%SystemRoot%\System32\Winevt\Logs\
.
Если вам нужно очистить их все – это будет утомительно вручную прощелкать все разделы Event Viewer и очистить каждый журнал. В этом случае для удаления событий лучше использовать PowerShell или командную строку.
Циклы
В PowerShell существует несколько видов циклов:
- Цикл с предусловием
while
:
$counter = 0 while ($counter -lt 5) { Write-Host "Counter is $($counter)" $counter++ }
- Цикл с постусловием истинным
do while
:
$counter = 0 do { Write-Host "Counter is $($counter)" $counter++ } while ($counter -lt 5)
- Цикл с постусловием ложным
do until
:
$counter = 0 do { Write-Host "Counter is $($counter)" $counter++ } until ($counter -ge 5)
- Цикл с известным числом итераций
for
:
for ($i = 0; $i -lt 5; $i++) { Write-Host "Iteration is $i" }
- Цикл с перебором элементов коллекции
foreach
:
$numbers = 1..5 foreach ($num in $numbers) { Write-Host "Number is $num" }
Во всех случаях синтаксис похож на синтаксис условных операторов: в круглых скобках указывается условие или параметры, а в фигурных скобках — код, который выполняется внутри цикла.
Условия
Условные операторы в PowerShell создаются с использованием ключевых слов if
, elseif
и else
. В круглых скобках указывается само условие, а в фигурных скобках содержится код, который выполняется при выполнении условия. Например:
$Number = 123 if ($Number -gt 0) { Write-Host 'Число больше нуля' } elseif ($Number -lt 0) { Write-Host 'Число меньше нуля' } else { Write-Host 'Число равно нулю' } Результат выполнения кода: Число больше нуля
Кроме того, условия также можно задавать с помощью ключевого слова switch
. Например:
$Day = 5 switch ($Day) { 1 { Write-Host 'Понедельник' } 2 { Write-Host 'Вторник' } 3 { Write-Host 'Среда' } 4 { Write-Host 'Четверг' } 5 { Write-Host 'Пятница' } 6 { Write-Host 'Суббота' } 7 { Write-Host 'Воскресенье' } } Результат выполнения кода: Пятница
Задача 3
Внезапно оказалось, что грузить и анализировать все аудиозаписи полностью очень дорого, такого бюджета у проекта не было. Быстро прослушав какие-то части и прогнав несколько сотен через бесплатные или десктопные STT решения, я обнаружил, что поздравления встречаются только в конце аудиофайла. Появилась идея отрезать только последние 30 секунд и проанализировать их. Установив в python модуль ffmpeg и прописав в windows PATH путь к кодеку удалось решить задачу вот так:
import os
import ffmpeg
from pydub import AudioSegment
mp3_folder = 'c:\\speech_sense\\upload_data\\calls\\'
wave_folder = 'c:\\speech_sense\\upload_data\\calls\\wave\\'
finish_fragment_folder = 'c:\\speech_sense\\upload_data\\calls\\wave\\finish_fragment\\'
def convert_mp3_to_wav(mp3_path, wav_path):
"""
Конвертируем MP3 в WAV используя модуль и установленный кодек ffmpeg.
"""
try:
ffmpeg.input(mp3_path).output(wav_path).run()
print(f"Converted {mp3_path} to {wav_path}")
except Exception as e:
print(f"Error converting {mp3_path} to WAV: {e}")
def extract_last_30_seconds(wav_path, output_path):
"""
Извлекаем последние 30 секунд в WAV файле.
"""
try:
audio = AudioSegment.from_wav(wav_path)
last_30_seconds = audio[-30000:] # оставляем последние 30000 мс (30 секунд)
last_30_seconds.export(output_path, format="wav")
print(f"Extracted last 30 seconds to {output_path}")
except Exception as e:
print(f"Error extracting last 30 seconds from {wav_path}: {e}")
if __name__ == "__main__":
# перебираем все файлы и конвертируем.
for filename in os.listdir(mp3_folder):
if filename.endswith('.mp3'):
mp3_file = os.path.join(mp3_folder, filename)
wave_filename = f"{os.path.splitext(filename)[0]}.wav"
wav_file = os.path.join(wave_folder, wave_filename)
finish_fragment_filename = f"{os.path.splitext(filename)[0]}_last_30_seconds.wav"
output_last_30_seconds = os.path.join(finish_fragment_folder, finish_fragment_filename)
# Если Вам, уважаемый читатель, кажется, что решение Задачи 1 не подходит,
# Просто сотрите символ комментария со стороки внизу.
# Функция convert_mp3_to_wav() решает задачу 1 средствами python
# convert_mp3_to_wav(mp3_file, wav_file)
extract_last_30_seconds(wav_file, output_last_30_seconds)
На calls\wave\finish_fragment\ повторно пришлось прогнать скрипт из Задачи 2 и получить метаданные уже по обрезанным фрагментам.
Задача 5
Начальные условия задачи были такие:
У меня есть 25000 готовых к загрузке аудиофайлов.
К каждому аудиофайлу созданы метаданные в .json с таким-же названием.
Примера с пакетной загрузкой в документации Яндекса нет.
Грузить файлы я умею только по одному.
Если прописать команду загрузки файла (см. первую часть статьи) в файл PowerShell .ps1 и запустить – ничего, кроме сообщения, что команду выполнить нельзя, не происходит.
Проблему с запуском файлов .ps1 я решил вот так: (https://ru.stackoverflow.com/questions/935212/powershell-выполнение-сценариев-отключено-в-этой-системе)
Открываем терминал с правами администратора
Пишем и запускаем: Set-ExecutionPolicy RemoteSigned
На вопрос отвечаем: A (Да для всех)
Далее я создал каждому аудиофайлу свой файл .ps1 для загрузки в SpeechSense.
import os
wave_directory = 'c:\\speech_sense\\upload_data\\calls\\wave\\finish_fragment\\'
output_directory = 'c:\\speech_sense\\upload_data\\calls\\powershell\\'
# Constants for connection ID and key
CONNECTION_ID = 'ID подключения' # Замените на свой
KEY = 'API_KEY' # Замените на свой
def generate_powershell_script(audio_filename):
# Определяем имя файла для метаданных в .json взяв исходное имя файла без расширения
base_name = os.path.splitext(audio_filename)[0]
json_filename = f"{base_name}.json"
# пишем команду PowerShell которая нужна для загрузки
# обратите внимание, где стоят кавычки "". Без них .ps1 ничего не запускал
cmd = f'py upload_grpc.py --audio-path "{wave_directory}\\{audio_filename}" --meta-path "{wave_directory}\\{json_filename}" --connection-id {CONNECTION_ID} --key {KEY}'
# Имя скрипта PowerShell
ps_script_filename = f"{base_name}.ps1"
# Пишем команду в файл PowerShell
with open(os.path.join(output_directory, ps_script_filename), 'w') as ps_script_file:
ps_script_file.write(cmd)
print(f"Generated {ps_script_filename}")
def main():
# Проверяем, существует ли основная директория
if not os.path.isdir(wave_directory):
print(f"The directory {wave_directory} does not exist.")
return
# Формируем скрипт PowerShell для каждого файла .wav в директории
for filename in os.listdir(wave_directory):
if filename.endswith('.wav'):
generate_powershell_script(filename)
if __name__ == '__main__':
main()
Задача 4
Все аудиозаписи в проекте рассортированы по отдельным папкам, по дням для каждого подрядчика. Подрядчиков десятки, нужно собрать все MP3 файлы мне на компьютер, в папку calls.
Сразу признаюсь, что с автоматизацией этой задачи я не справился. Python молча и напрочь отказался создавать список директорий. Падал с ошибкой в строке 6. Причин такого поведения я обнаружить или нагуглить не смог. Подозреваю, что дело в пробелах, русских буквах в названиях директорий или в том, что файлы лежат на сетевых дисках.
Код решения я всё равно выложу, возможно кто-то увидит, объяснит и поправит ошибки. Буду благодарен.
import os
import shutil
import glob
# список directories и переменную directories_list python отказывался создавать
directories = ['/path/to/dir1', '/path/to/dir2', '/path/to/dir3']
directories_list = '/path/to/dir3'
destination_dir = 'c:\\speech_sense\\upload_data\\calls\\'
os.makedirs(destination_dir, exist_ok=True)
def copy_mp3_files(directories, destination):
for directory in directories:
mp3_files = glob.glob(os.path.join(directory, '*.mp3'))
for mp3 in mp3_files:
shutil.copy(mp3, destination)
copy_mp3_files(directories, destination_dir)
Задача 2
Для подгрузки аудиозаписи в SpeechSense желательно иметь файл с метаданными аудиозаписи. Инструкция предлагает 2 варианта, создать .json файл к каждому аудио самостоятельно, либо, при отсутствии файла, использовать всегда вот такой формат:
now = datetime.datetime.now().isoformat()
metadata = {
'operator_name': 'Operator',
'operator_id': '1111',
'client_name': 'Client',
'client_id': '2222',
'date': str(now),
'date_from': '2023-09-13T17:30:00.000',
'date_to': '2023-09-13T17:31:00.000',
'direction_outgoing': 'true',
}
В моем случае метаданные я мог получить только из имени файла, и было два способа, которыми эти имена формировались.
В первом случае в имени файла был только ID звонка.
import os
import json
from datetime import datetime
# Папка с файлами в формате wave из предыдущего скрипта.
wave_folder = 'c:\\speech_sense\\upload_data\\calls\\wave\\'
# Получение текущей даты в формате YYYY-MM-DDTHH:MM:SS.SSS.
# Яндекс требует все даты именно в таком формате, пришлось повозиться, чтобы
# отформатировать время корректно. При любых отклонениях от этого формата
# загрузка аудио в SpeechSense заканчивается ошибкой.
current_date = datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3]
# Проходим по всем файлам в папке
for filename in os.listdir(wave_folder):
if filename.endswith('.wav'):
# Создание шаблона JSON для каждого файла
data = {
"operator_name": os.path.splitext(filename)[0],
"operator_id": os.path.splitext(filename)[0],
"client_name": "Client",
"client_id": "1",
"date": current_date,
"direction_outgoing": "true",
"language": "ru"
}
# Для имени и ID оператора используем ID из названия файла.
# По этому ID можно будет узнать, в каком файле найдены поздравления.
# Имя JSON файла
json_filename = f"{os.path.splitext(filename)[0]}.json"
# Запись данных в JSON файл. Обязательно указывать кодировку windows-1251
# без параметра или в UTF-8 SpeechSense преобразует все русские буквы в кракозябры.
with open(os.path.join(wave_folder, json_filename), 'w', encoding='windows-1251') as json_file:
json.dump(data, json_file, ensure_ascii=False, indent=4)
print("JSON файлы успешно созданы.")
Во втором случае в имени файла была информация о дате и времени звонка, контактном телефоне клиента и ID звонка. Шаблон имени файла был такой “YYYYMMDD-HHMM-toXXXXXXXXXX-ID.wav”. Решение выглядит вот так
import os
import json
from datetime import datetime
# Папка с файлами
wave_folder = 'c:\\speech_sense\\upload_data\\calls\\wave\\'
for filename in os.listdir(wave_folder):
if filename.endswith('.wav'):
# разбиваем имя файла по разделителю "-"
data = os.path.splitext(filename)[0]
parts = data.split("-")
# склеиваем первую и вторую часть имени, где остаются дата и время звонка.
date_str = parts[0] + parts[1]
# приводим к необходимому для SpeechSense формату даты
date_object = datetime.strptime(date_str, "%Y%m%d%H%M")
formatted_date = date_object.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3]
data = {
"operator_name": "Operator",
"operator_id": parts[3],
"client_name": "Respondent",
"client_id": parts[2],
"date": formatted_date,
"direction_outgoing": "true",
"language": "ru"
}
# пишем JSON файл, не забыв указать кодировку.
json_filename = f"{os.path.splitext(filename)[0]}.json"
with open(os.path.join(wave_folder, json_filename), 'w', encoding='windows-1251') as json_file:
json.dump(data, json_file, ensure_ascii=False, indent=4)
print("JSON файлы успешно созданы.")
Я понимаю, что тут найдутся специалисты, которые справедливо упрекнут, что нарушен принцип DRY, код повторяется и при желании не сложно написать одну функцию, которая будет извлекать метаданные из имен файла любого формата. Да, всё верно, рефакторинг кода уже запланирован на будущее. А тут изначально и планировались и проект по документации должен хранить в именах файлов только ID. Реальность оказалась сложнее. Вторая часть задачи возникла совершенно внезапно, когда весь код уже был написан.
Как получить данные из Active Directory и сохранить их в книге Excel?
Рассмотрим практический пример как можно использовать PowerShell для получения данных из Excel. Например, вы хотите получить для каждого пользователя в Excel файле получить информацию из Active Directory. Например, его телефон (атрибут telephoneNumber), отдел (department) и email адрес (mail).
В результате в Excel файле для каждого пользователя были добавлены столбцы с информацией из AD.
Рассмотрим еще один пример построения отчета с помощью PowerShell и Excel. Допустим, вам нужно построить Excel отчет о состоянии службы Print Spooler на всех серверах домена.
- Вы можете поручить сотруднику отдела кадров вести реестр пользователей в Excel, а затем с помощью PowerShellс скриптов создавать новых пользователей в AD (New-ADUser) или обновлять их данные (Set-ADUser). Можно делегировать этому пользователю права на изменение этих атрибутов.
- Пример скрипта PowerShell для рассылки писем из Outlook по списку пользователям из Excel файла.
Работа с файлами
PowerShell предоставляет удобные средства для работы с файлами. Вот некоторые ключевые методы:
Для создания файла используйте командлет New-Item
с указанием пути к файлу:
New-Item -Path "C:\путь\к\файлу\новыйфайл.txt" -ItemType File
Чтобы записать данные в файл, используйте Out-File
или Set-Content
:
"Содержимое файла" | Out-File -FilePath "C:\путь\к\файлу\новыйфайл.txt" Set-Content -Path "C:\путь\к\файлу\новыйфайл.txt" -Value "Новое содержимое файла"
Для чтения содержимого файла в массив используйте Get-Content
:
$содержимое = Get-Content -Path "C:\путь\к\файлу\новыйфайл.txt"
Для получения информации о файле (размер, дата создания и др.) используйте Get-Item
:
$информацияОФайле = Get-Item -Path "C:\путь\к\файлу\новыйфайл.txt"
Для копирования файла в другое место используйте Copy-Item
:
Copy-Item -Path "C:\путь\к\файлу\новыйфайл.txt" -Destination "C:\путь\к\копия\новыйфайл.txt"
Для удаления файла воспользуйтесь командлетом Remove-Item
:
Remove-Item -Path "C:\путь\к\файлу\новыйфайл.txt" -Force
Помните, что операции удаления файлов необратимы, поэтому будьте осторожны при их использовании.
Записать значение в ячейку Excel из PowerShell
Вы можете изменить значение любой ячейки в книге Excel. Например, вы хотите изменить должность пользователя в файле.
Получить текущее значение ячейки:
Присвойте новое значение ячейке:
$ExcelWorkSheet.cells.Item(2, 3) = 'Начальник отдела продаж'
Изменить размер шрифта и выделить новое значение жирным:
$ExcelWorkSheet.cells.Item(2, 3).Font.Bold = $true
$ExcelWorkSheet.cells.Item(2, 3).Font.size=14
Сохранить изменения и закрыть книгу Excel:
Закрыть приложение Excel:
Откройте XLSX файл и проверьте, что данные и шрифт в указанной ячейки были изменены.
Если вам нужно создать новый лист в документе Excel:
$ExcelWorkSheet = $ExcelWorkBook.Worksheets.Add()
$ExcelWorkSheet.Name = "NewSheet"
Удалить целиком столбец или строку:
$ExcelWorkSheet.cells.Item(5, 1).EntireRow.Delete()
$ExcelWorkSheet.cells.Item(2, 1).EntireColumn.Delete()
Работа в PowerShell ISE
Командная оболочка PowerShell представляет собой удобный инструмент для выполнения малых, кратких однострочных задач. Однако для создания и сохранения более сложных сценариев существует интегрированная среда разработки скриптов PowerShell ISE.
PowerShell ISE представляет собой инструмент, состоящий из трех основных панелей:
- Область скриптов в верхней части экрана, предназначенная для написания сценариев.
- Консольная область в нижней части экрана, которая функционирует как обычный терминал, позволяя вводить команды в интерактивном режиме.
- Панель команд в правой части экрана, предоставляющая полное руководство по командам PowerShell. В ней также есть конструктор, который помогает задать значения нужных параметров.
Комментарии в коде
Вот пример PowerShell скрипта с комментариями:
# Это комментарий в одну строку, начинается с символа '#' и продолжается до конца строки. # Пример переменной $имя = "John" $возраст = 30 # Вывод информации Write-Host "Привет, $имя! Тебе $возраст лет." # Это многострочный комментарий, который начинается с '<#' и заканчивается '#>'. <# Этот блок комментария может быть многострочным и располагаться на нескольких строках, чтобы объяснить более сложные участки кода. #> # Функция для сложения двух чисел function Сложить-Числа { param( [int]$число1, [int]$число2 ) $результат = $число1 + $число2 return $результат } # Вызов функции и вывод результата $результатСложения = Сложить-Числа -число1 5 -число2 7 Write-Host "Результат сложения: $результатСложения"
Хорошая практика — комментировать код таким образом, чтобы другие разработчики (или вы в будущем) могли легко понять, как работает код и какие цели преследовались при его написании.
Советы по написанию хорошего кода:
- Применяйте нотацию PascalCase для названий командлетов, функций, параметров, свойств, методов, переменных и классов. Разработчики Powershell выпустили для этого гайд. Не рекомендуется:
get-service
,Get-service
,GET-SERVICE
. Рекомендуется:Get-Service
. - Используйте полные названия командлетов. Алиасы удобны для интерактивного режима, но в скриптах они могут затруднить понимание. Не рекомендуется:
dir
,gci
,ls
. Рекомендуется:Get-ChildItem
. - Применяйте стиль One True Brace для форматирования вложенных блоков кода. Если вы используете фигурные скобки, внутренний код отделяется табуляцией (четыре пробела), а фигурные скобки размещаются следующим образом:
if ($var1 -eq $var2) { # Код внутри условия } else { # Код внутри else # Еще код внутри else }
Исключение: когда код внутри фигурных скобок небольшой, его можно записать в одну строку:
Get-ChildItem | Where-Object { $_.Length -gt 10mb }
Запуск скриптов
В PowerShell ISE имеется возможность выполнять код как целиком, так и частично, а также предоставляются инструменты для отладки. Скрипты сохраняются в файлах с расширением .ps1
. Однако запустить скрипт, просто дважды щелкнув по нему, не получится. Вместо этого вы можете нажать правую кнопку мыши и выбрать опцию Выполнить с помощью PowerShell
.
Также существует возможность запуска скрипта из оболочки. Например, предположим, у вас есть файл скрипта test_script.ps1 в каталоге C:\Scripts
. Вы можете выполнить его двумя способами:
- Используя команду
PowerShell -File C:\Scripts\test_script.ps1
из любого места. Это позволяет запустить скрипт, указав полный путь к файлу. - Используя команду
.\test_script.ps1
, если вы находитесь в каталогеC:\Scripts
. Это запустит скрипт, находясь в том же каталоге, что и файл скрипта.
Такие методы позволяют управлять выполнением PowerShell скриптов из разных мест и с разных уровней оболочки.
Политика выполнения. Как разрешить выполнения скриптов
По умолчанию запрещено выполнение файлов с PowerShell-скриптами, и это сделано с целью обеспечения безопасности. Вы можете узнать текущую политику выполнения с помощью командлета Get-ExecutionPolicy
. Вот какие варианты политики выполнения могут быть доступны:
- Restricted (Установлена по умолчанию) — запрещено выполнение любых скриптов. Это означает, что нельзя будет запустить ни один скрипт.
- AllSigned — разрешено выполнение только тех скриптов, которые были подписаны доверенным разработчиком. Это обеспечивает повышенный уровень безопасности, так как только подписанные и проверенные скрипты могут быть выполнены.
- RemoteSigned — разрешено выполнение подписанных доверенным разработчиком скриптов, а также собственных скриптов. Это предоставляет баланс между безопасностью и удобством, позволяя запускать свои скрипты.
- Unrestricted — разрешено выполнение любых скриптов без каких-либо ограничений. Это предоставляет наивысший уровень гибкости, но может повысить риск безопасности.
Чтобы ваши файлы с расширением .ps1 запускались, вам следует изменить политику выполнения на RemoteSigned. Для этого выполните следующие шаги:
- Откройте PowerShell от имени администратора. Для этого щелкните правой кнопкой мыши по значку PowerShell на панели задач или в меню «Пуск» и выберите «Запуск от имени администратора».
- В открывшемся окне PowerShell введите следующую команду и нажмите Enter:
Set-ExecutionPolicy RemoteSigned
- Подтвердите изменение политики выполнения, нажав клавишу
Y
(Yes).
Теперь вы сможете запускать свои файлы .ps1 без ограничений. Однако, имейте в виду, что изменение политики выполнения может повлиять на безопасность системы, поэтому будьте осторожны и убедитесь, что вы запускаете только те скрипты, которые вы знаете и доверяете.
Удаление логов Windows из командной строки
Для очистки журналов Windows из командной строки используется утилита wevtutil.exe.
Вывести список зарегистрированных в Windows журналов событий:
или короткий вариант:
Для удаления событий из одного конкретного журнала, скопируйте его имя и выполните команду:
WevtUtil cl Microsoft-Windows-GroupPolicy/Operational
Перед очисткой можно создать резервную копию событий в журнале в отдельный файл:
WevtUtil cl Microsoft-Windows-GroupPolicy/Operational /bu:GPOLOG_Bak.evtx
Можно очистить сразу все журналы событий из cmd.exe:
for /F "tokens=*" %1 in ('wevtutil.exe el') DO wevtutil.exe cl "%1"
Для BAT файла нужно использовать немного другой синтаксис:
for /F "tokens=*" %%1 in ('wevtutil.exe el') DO wevtutil.exe cl "%%1"
Еще несколько вариантов скриптов
1. Рекламка книги из онлайн библиотеки
convert -resize 365x528! book1.png book1.png
convert "book1.png" +clone -background black -shadow 80x3+5+5 +swap -background none -layers merge +repage shadow.png
magick bookpattern.png shadow.png -geometry +125+510 -composite book.png
magick book.png book1.png -geometry +120+500 -composite book.png
magick book.png bookframe.png -geometry +120+500 -composite book.png
magick book.png -pointsize 32 -fill white -font Sylfaen -gravity South -annotate -210+120 'Королева Марго' book.png
magick book.png -pointsize 22 -fill grey -font Tahoma -gravity South -annotate -210+90 'Александр Дюма' book.png
magick book.png -pointsize 88 -fill white -font Sylfaen -gravity Center -annotate +0-290 'Королева Марго' book.png
magick book.png -pointsize 24 -fill grey -font Tahoma -gravity Center -annotate +0-220 'Александр Дюма в библиотеке Two-Digit Athenaeum'book.png
magick book.png -pointsize 66 -fill grey -font Sylfaen -gravity South -annotate +160+330 'по коду:' book.png
magick book.png -pointsize 120 -fill white -font Tahoma -gravity South -annotate +200+195 '9VAN2' book.png
convert -resize 768x768 book.png book.png
P.S. Из нового – строки 2 и 3. В строке 2 создается png тени от book1.png, а в 3 – тень накладывается на фон. На фоне уже есть темное пятно, да, но тень из скрипта тоже рабочая.
Функция СформироватьРекламуКниги(Знач Книга) Экспорт
ФонДД = Справочники.Файлы.РК_Фон.Файл.Получить();
Фон = ПолучитьИмяВременногоФайла(".png");
ФонДД.Записать(Фон);
РамкаДД = Справочники.Файлы.РК_Рамка.Файл.Получить();
Рамка = ПолучитьИмяВременногоФайла(".png");
РамкаДД.Записать(Рамка);
ОбъектКнига = Книга.ПолучитьОбъект();
КартинкаКнигиДД = ОбъектКнига.КартинкаДвоичные.Получить();
КартинкаКниги = ПолучитьИмяВременногоФайла(".png");
КартинкаКнигиДД.Записать(КартинкаКниги);
КодКниги = ОбъектКнига.Код;
НазваниеКниги = ОбъектКнига.Наименование;
АвторКниги = ОбъектКнига.Автор.Имя + " " + ОбъектКнига.Автор.Фамилия;
КартинкаОбработанная = ПолучитьИмяВременногоФайла(".png");
МассивВФ = Новый Массив;
МассивВФ.Добавить(Фон);
МассивВФ.Добавить(Рамка);
МассивВФ.Добавить(КартинкаКниги);
ИмяСкрипта = ПолучитьИмяВременногоФайла(".ps1");
ТекстСкрипта = Новый ТекстовыйДокумент();
ТекстСкрипта.УстановитьТекст(
"convert -resize 365x528! """
+ КартинкаКниги
+ """ """
+ КартинкаКниги
+ """"
+ Символы.ПС
+ "magick """
+ Фон
+ """ """
+ КартинкаКниги
+ """ -geometry +120+500 -composite """
+ КартинкаОбработанная
+ """"
+ Символы.ПС
+ "magick """
+ КартинкаОбработанная
+ """ """
+ Рамка
+ """ -geometry +120+500 -composite """
+ КартинкаОбработанная
+ """"
+ Символы.ПС
+ "magick """
+ КартинкаОбработанная
+ """ -pointsize 32 -fill white -font Sylfaen -gravity South -annotate -210+120 '"
+ НазваниеКниги
+ "' """
+ КартинкаОбработанная
+ """"
+ Символы.ПС
+ "magick """
+ КартинкаОбработанная
+ """ -pointsize 22 -fill grey -font Tahoma -gravity South -annotate -210+90 '"
+ АвторКниги
+ "' """
+ КартинкаОбработанная
+ """"
+ Символы.ПС
+ "magick """
+ КартинкаОбработанная
+ """ -pointsize 88 -fill white -font Sylfaen -gravity Center -annotate +0-290 '"
+ НазваниеКниги
+ "' """
+ КартинкаОбработанная
+ """"
+ Символы.ПС
+ "magick """
+ КартинкаОбработанная
+ """ -pointsize 24 -fill grey -font Tahoma -gravity Center -annotate +0-220 '"
+ АвторКниги
+ " в библиотеке Two-Digit Athenaeum'"""
+ КартинкаОбработанная
+ """"
+ Символы.ПС
+ "magick """
+ КартинкаОбработанная
+ """ -pointsize 66 -fill grey -font Sylfaen -gravity South -annotate +160+330 'по коду:' """
+ КартинкаОбработанная
+ """"
+ Символы.ПС
+ "magick """
+ КартинкаОбработанная
+ """ -pointsize 120 -fill white -font Tahoma -gravity South -annotate +200+195 '"
+ КодКниги
+ "' """
+ КартинкаОбработанная
+ """"
+ Символы.ПС
+ "convert -resize 768x768 """
+ КартинкаОбработанная
+ """ """
+ КартинкаОбработанная
+ """"
);
ТекстСкрипта.Записать(ИмяСкрипта, КодировкаТекста.UTF8);
КодВозврата = 0;
ЗапуститьПриложение("powershell -file " + ИмяСкрипта, ,Истина, КодВозврата);
УдалитьФайлы(ИмяСкрипта);
СтруктураВозврата = Новый Структура;
СтруктураВозврата.Вставить("Картинка", КартинкаОбработанная);
СтруктураВозврата.Вставить("МассивВФ", МассивВФ);
Возврат СтруктураВозврата
КонецФункции
2. Создание карточек разного размера по пути к файлу
Сразу перейду к 1С. Ничего сложного этот код не делает: берет путь к файлу из параметра и обходит соответствие, где ключ – имя файла, а значение – размер. Сохраняется все в webp рядом с основной картинкой
Процедура СоздатьКарточки(Знач ПутьКОригиналу) Экспорт
Картинка = Новый Файл(ПутьКОригиналу);
Путь = Картинка.Путь;
Размеры = Новый Соответствие;
Размеры.Вставить("small" , "175x270");
Размеры.Вставить("medium" , "295x455");
Для Каждого Размер Из Размеры Цикл
РазмерМассив = СтрРазделить(Размер.Значение, "x");
Ширина = РазмерМассив[0];
Высота = РазмерМассив[1];
ИмяСкрипта = ПолучитьИмяВременногоФайла(".ps1");
ТекстСкрипта = Новый ТекстовыйДокумент();
ТекстСкрипта.УстановитьТекст(
"magick convert -resize " + Ширина + "x -unsharp 0x0.55+0.55+0.008 -quality 90 "
+ ПутьКОригиналу
+ " "
+ Путь
+ Размер.Ключ
+ ".webp"
+ Символы.ПС +
"convert "
+ Путь
+ Размер.Ключ
+ ".webp"
+ " -resize " + Размер.Значение + "! -gravity North -extent " + Размер.Значение + " "
+ Путь
+ Размер.Ключ
+ ".webp"
);
ТекстСкрипта.Записать(ИмяСкрипта, КодировкаТекста.UTF8);
КодВозврата = 0;
ЗапуститьПриложение("powershell -file " + ИмяСкрипта + " -noexit", ,Истина, КодВозврата);
УдалитьФайлы(ИмяСкрипта);
КонецЦикла;
КонецПроцедуры
Из незнакомого здесь: –quality и –unsharp. –quality может резать качество, что уменьшает вес картинки. Как работает unsharp никто не знает, но он снижает блюр при изменении размеров.
3. Еще один способ рисовать текст
Рисует текст с подкладкой. Для этого используется вообще другой механизм: не -annotate, а –draw
magick event.jpg -fill white -stroke white -undercolor black -font Sylfaen -pointsize 28 -gravity SouthWest -draw "text 130,65 'Пабло Пикассо, Симона де Бовуар, Жан-Поль Сартр,\n Альбер Камю и другие'" event.jpg
–stroke определяет цвет контура символов, –fill – цвет заливки, –udercolor – цвет подложки. 130, 65 после текст – те же +130+65 у annotate
Важно: \n – перенос строки
"magick """
+ КартинкаОбработанная
+ """ -fill white -stroke white -undercolor black -font Tahoma -pointsize 18 -gravity SouthWest -draw ""text 130,30 '"
+ Место
+ ", "
+ ДатаСобытия
+ "'"" """
+ КартинкаОбработанная
+ """"
Вот и вся “картиночная магия”. Надеюсь, было полезно.