302 lines
11 KiB
PowerShell
302 lines
11 KiB
PowerShell
$configPath = Join-Path $PSScriptRoot "config.json"
|
|
|
|
function Load-Config {
|
|
if (Test-Path $configPath) {
|
|
try {
|
|
$script:config = Get-Content $configPath | ConvertFrom-Json
|
|
$script:txtSiteUrl.Text = $config.SiteUrl
|
|
return $true
|
|
}
|
|
catch {
|
|
Write-Error "Invalid config file: $_"
|
|
return $false
|
|
}
|
|
}
|
|
return $false
|
|
}
|
|
|
|
function Save-Config {
|
|
param(
|
|
[string]$SiteUrl,
|
|
[string]$ProductionLibrary,
|
|
[string]$TempLibrary
|
|
)
|
|
|
|
$config = @{
|
|
SiteUrl = $SiteUrl
|
|
ProductionLibrary = $ProductionLibrary
|
|
TempLibrary = $TempLibrary
|
|
}
|
|
|
|
$config | ConvertTo-Json | Set-Content $configPath
|
|
}
|
|
|
|
function Connect-SharePoint {
|
|
return Connect-Graph
|
|
}
|
|
|
|
function List-XlsFiles {
|
|
try {
|
|
$script:txtStatus.Text += "Connecting to SharePoint...`n"
|
|
if (-not (Connect-SharePoint)) {
|
|
throw "Failed to connect to SharePoint"
|
|
}
|
|
|
|
$script:txtStatus.Text += "Getting site...`n"
|
|
$site = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/sites/sutterhill.sharepoint.com:/sites/tax" -ErrorAction Stop
|
|
|
|
$script:txtStatus.Text += "Getting document library...`n"
|
|
$drives = Get-MgSiteDrive -SiteId $site.id
|
|
$libraryName = if ($script:txtProdLib.Text -eq "Shared Documents") {
|
|
"Documents"
|
|
} else {
|
|
$script:txtProdLib.Text
|
|
}
|
|
$drive = $drives | Where-Object { $_.Name -eq $libraryName }
|
|
|
|
if (-not $drive) {
|
|
throw "Library not found: $libraryName. Available libraries: $($drives.Name -join ', ')"
|
|
}
|
|
|
|
$script:txtStatus.Text += "Getting root folder...`n"
|
|
$root = Get-MgDriveRoot -DriveId $drive.Id
|
|
|
|
$fileList = @()
|
|
$folderPath = $script:txtFolder.Text
|
|
|
|
$script:txtStatus.Text += "Searching for XLS files...`n"
|
|
|
|
# If a specific folder is selected, search only in that folder
|
|
if (-not [string]::IsNullOrWhiteSpace($folderPath)) {
|
|
$script:txtStatus.Text += "Searching in folder: $folderPath`n"
|
|
# Get the folder ID first
|
|
# Construct the correct URI for the folder
|
|
# Remove the /sites/tax/Shared Documents part from the folder path
|
|
$relativePath = $folderPath.Replace("/sites/tax/Shared Documents/", "").TrimStart("/")
|
|
|
|
# URL encode the relative path
|
|
$encodedPath = [System.Web.HttpUtility]::UrlEncode($relativePath)
|
|
|
|
$folderUri = "https://graph.microsoft.com/v1.0/drives/$($drive.Id)/root:/$encodedPath"
|
|
$script:txtStatus.Text += "Folder URI: $folderUri`n"
|
|
try {
|
|
$folderItem = Invoke-MgGraphRequest -Method GET -Uri $folderUri -ErrorAction Stop
|
|
} catch {
|
|
throw "Folder not found: $($_.Exception.Message)"
|
|
}
|
|
$items = Get-MgDriveItemChild -DriveId $drive.Id -DriveItemId $folderItem.id
|
|
} else {
|
|
$script:txtStatus.Text += "Searching in root folder`n"
|
|
$items = Get-MgDriveItemChild -DriveId $drive.Id -DriveItemId $root.Id
|
|
}
|
|
|
|
foreach ($item in $items) {
|
|
$script:txtStatus.Text += "Checking file: $($item.Name)`n"
|
|
if ($item.Name -like "*.xls" -and $item.Name -notlike "*.xlsx") {
|
|
$fileList += [PSCustomObject]@{
|
|
OriginalPath = $item.WebUrl
|
|
OriginalFileName = $item.Name
|
|
TempPath = "$($script:txtTempLib.Text)/$($item.Name)"
|
|
}
|
|
$script:txtStatus.Text += "Found XLS file: $($item.Name)`n"
|
|
}
|
|
}
|
|
|
|
if ($fileList.Count -gt 0) {
|
|
$script:txtStatus.Text += "Saving file list...`n"
|
|
$fileList | ConvertTo-Json | Out-File "$env:TEMP\FileList.json"
|
|
$script:txtStatus.Text += "Found $($fileList.Count) XLS files`n"
|
|
} else {
|
|
$script:txtStatus.Text += "No XLS files found`n"
|
|
}
|
|
}
|
|
catch {
|
|
$script:txtStatus.Text += "Error listing files: $($_.Exception.Message)`n"
|
|
}
|
|
}
|
|
|
|
function Convert-Files {
|
|
if (-not (Connect-SharePoint)) {
|
|
}
|
|
|
|
$excel = New-Object -ComObject Excel.Application
|
|
$excel.Visible = $false
|
|
|
|
try {
|
|
Get-PnPFile -Url "/sites/yoursite/$($script:txtTempLib.Text)/FileList.json" -Path $env:TEMP -Filename "FileList.json"
|
|
$files = Get-Content "$env:TEMP\FileList.json" | ConvertFrom-Json
|
|
|
|
foreach ($file in $files) {
|
|
try {
|
|
$workbook = $excel.Workbooks.Open((Convert-PnPFile -Url $file.OriginalPath -Path $env:TEMP -Filename $file.OriginalFileName))
|
|
$newName = [System.IO.Path]::ChangeExtension($file.OriginalFileName, ".xlsx")
|
|
$workbook.SaveAs([System.IO.Path]::Combine($env:TEMP, $newName), 51) # 51 = xlsx
|
|
Add-PnPFile -Folder "Documents" -Path "$env:TEMP\$newName"
|
|
$script:txtStatus.Text += "Converted $($file.OriginalFileName) to XLSX`n"
|
|
}
|
|
finally {
|
|
$workbook.Close()
|
|
}
|
|
}
|
|
}
|
|
finally {
|
|
$excel.Quit()
|
|
}
|
|
}
|
|
|
|
function Move-Files {
|
|
if (-not (Connect-SharePoint)) {
|
|
}
|
|
|
|
$files = Get-Content "$env:TEMP\FileList.json" | ConvertFrom-Json
|
|
|
|
foreach ($file in $files) {
|
|
Move-PnPFile -SourceUrl $file.OriginalPath -TargetUrl $file.TempPath -Force
|
|
$xlsxPath = [System.IO.Path]::ChangeExtension($file.OriginalPath, ".xlsx")
|
|
Move-PnPFile -SourceUrl "$($script:txtProdLib.Text)/$xlsxPath" -TargetUrl $xlsxPath -Force
|
|
$script:txtStatus.Text += "Moved $($file.OriginalFileName) and its XLSX version`n"
|
|
}
|
|
}
|
|
function Get-FolderBrowser {
|
|
param (
|
|
[string]$ParentFolderUrl = ""
|
|
)
|
|
try {
|
|
# Get site ID first
|
|
$siteUrl = $script:txtSiteUrl.Text.TrimEnd('/')
|
|
|
|
# Get site directly using the URL
|
|
$encodedUrl = [System.Web.HttpUtility]::UrlEncode($siteUrl)
|
|
$site = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/sites/sutterhill.sharepoint.com:/sites/tax" -ErrorAction Stop
|
|
|
|
if (-not $site) {
|
|
throw "Site not found at $siteUrl"
|
|
}
|
|
|
|
$script:txtStatus.Text += "Found site: $($site.webUrl)`n"
|
|
|
|
# Get drive (document library)
|
|
$drives = Get-MgSiteDrive -SiteId $site.id
|
|
# Handle "Shared Documents" special case
|
|
$libraryName = if ($script:txtProdLib.Text -eq "Shared Documents") {
|
|
"Documents"
|
|
} else {
|
|
$script:txtProdLib.Text
|
|
}
|
|
$drive = $drives | Where-Object { $_.Name -eq $libraryName }
|
|
|
|
if (-not $drive) {
|
|
$script:txtStatus.Text += "Available libraries: $($drives.Name -join ', ')`n"
|
|
throw "Library not found: $libraryName"
|
|
}
|
|
|
|
# Get root folder first
|
|
# Get root folder first
|
|
if ($ParentFolderUrl) {
|
|
# Get the folder ID first
|
|
# Construct the correct URI for the folder
|
|
# Remove the /sites/tax/Shared Documents/ part from the folder path
|
|
$relativePath = $ParentFolderUrl.Replace("/sites/tax/Shared Documents/", "").TrimStart("/")
|
|
|
|
# URL encode the relative path
|
|
$encodedPath = [System.Web.HttpUtility]::UrlEncode($relativePath)
|
|
|
|
$folderUri = "https://graph.microsoft.com/v1.0/drives/$($drive.Id)/root:/$encodedPath"
|
|
$script:txtStatus.Text += "Folder URI: $folderUri`n"
|
|
try {
|
|
$folderItem = Invoke-MgGraphRequest -Method GET -Uri $folderUri -ErrorAction Stop
|
|
} catch {
|
|
throw "Folder not found: $($_.Exception.Message)"
|
|
}
|
|
$root = $folderItem
|
|
}
|
|
else {
|
|
$root = Get-MgDriveRoot -DriveId $drive.Id
|
|
}
|
|
|
|
# Get folders using the root item's ID
|
|
$folders = Get-MgDriveItemChild -DriveId $drive.Id -DriveItemId $root.Id | Where-Object { $_.Folder }
|
|
|
|
# Create custom objects for the grid view
|
|
$folderObjects = $folders | ForEach-Object {
|
|
[PSCustomObject]@{
|
|
Name = $_.Name
|
|
ServerRelativeUrl = "/sites/tax/Shared Documents/$($_.Name)"
|
|
IsFolder = $true # Add a property to indicate it's a folder
|
|
}
|
|
}
|
|
|
|
# Add ".." entry to go up a level if not at the root
|
|
if ($ParentFolderUrl) {
|
|
$parentUrl = Split-Path -Path $ParentFolderUrl -Parent
|
|
$folderObjects = @([PSCustomObject]@{
|
|
Name = ".."
|
|
ServerRelativeUrl = $parentUrl
|
|
IsFolder = $true
|
|
}) + $folderObjects
|
|
}
|
|
|
|
# Create a form and listbox for folder selection
|
|
$form = New-Object System.Windows.Forms.Form
|
|
$form.Text = "Select Folder"
|
|
$form.Size = New-Object System.Drawing.Size(400, 400)
|
|
$listBox = New-Object System.Windows.Forms.ListBox
|
|
$listBox.Size = New-Object System.Drawing.Size(360, 320)
|
|
$listBox.Location = New-Object System.Drawing.Point(10, 10)
|
|
$okButton = New-Object System.Windows.Forms.Button
|
|
$okButton.Location = New-Object System.Drawing.Point(150, 340)
|
|
$okButton.Size = New-Object System.Drawing.Size(75, 23)
|
|
$okButton.Text = "OK"
|
|
$cancelButton = New-Object System.Windows.Forms.Button
|
|
$cancelButton.Location = New-Object System.Drawing.Point(230, 340)
|
|
$cancelButton.Size = New-Object System.Drawing.Size(75, 23)
|
|
$cancelButton.Text = "Cancel"
|
|
$form.Controls.Add($listBox) | Out-Null
|
|
$form.Controls.Add($okButton) | Out-Null
|
|
$form.Controls.Add($cancelButton) | Out-Null
|
|
$form.FormBorderStyle = 'FixedDialog'
|
|
$form.StartPosition = 'CenterScreen'
|
|
$form.Add_Shown({$Form.Activate()})
|
|
# Populate listbox
|
|
foreach ($folder in $folderObjects) {
|
|
$listBox.Items.Add($folder.Name) | Out-Null
|
|
}
|
|
|
|
# Handle OK button click
|
|
$okButton.Add_Click({
|
|
$form.Tag = $listBox.SelectedItem
|
|
$form.Close()
|
|
})
|
|
|
|
# Handle Cancel button click
|
|
$cancelButton.Add_Click({
|
|
$form.Tag = $null
|
|
$form.Close()
|
|
})
|
|
|
|
# Show the Form as a Dialog
|
|
[void]$form.ShowDialog()
|
|
|
|
# Get the selected folder
|
|
$selected = $folderObjects | Where-Object {$_.Name -eq $form.Tag}
|
|
|
|
# If a folder is selected, browse into it
|
|
if ($selected -and $selected.IsFolder -eq $true -and $selected.Name -ne "..") {
|
|
return Get-FolderBrowser -ParentFolderUrl $selected.ServerRelativeUrl
|
|
}
|
|
elseif ($selected -and $selected.Name -eq "..") {
|
|
return Get-FolderBrowser -ParentFolderUrl $selected.ServerRelativeUrl
|
|
}
|
|
elseif ($selected) {
|
|
return $selected
|
|
}
|
|
else {
|
|
return $null
|
|
}
|
|
}
|
|
catch {
|
|
$script:txtStatus.Text += "Folder Error: $($_.Exception.Message)`n"
|
|
return $null
|
|
}
|
|
}
|