SharepointXLStoXLSX/SharePointFunctions.ps1

397 lines
15 KiB
PowerShell

# Load configuration from config.json
function Load-Config {
try {
$configPath = "$PSScriptRoot\config.json"
if (Test-Path $configPath) {
$script:config = Get-Content $configPath -Raw | ConvertFrom-Json
return $true
} else {
$script:txtStatus.Text += "Error loading configuration: $($_.Exception.Message)`n"
return $false
}
}
catch {
$script:txtStatus.Text += "Error loading configuration: $($_.Exception.Message)`n"
return $false
}
}
# Save configuration to config.json
function Save-Config {
param (
[string]$SiteUrl,
[string]$ProductionLibrary,
[string]$TempLibrary
)
try {
$configPath = "$PSScriptRoot\config.json"
$configData = @{
SiteUrl = $SiteUrl
ProductionLibrary = $ProductionLibrary
TempLibrary = $TempLibrary
}
$configJson = ConvertTo-Json -InputObject $configData -Compress
$configJson | Out-File $configPath
$script:txtStatus.Text += "Configuration saved successfully.`n"
} catch {
$script:txtStatus.Text += "Error saving configuration: $($_.Exception.Message)`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, but replace + with %20 for spaces
$encodedPath = [System.Web.HttpUtility]::UrlEncode($relativePath).Replace("+", "%20")
$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"
$selectFolderButton = New-Object System.Windows.Forms.Button
$selectFolderButton.Location = New-Object System.Drawing.Point(70, 340)
$selectFolderButton.Size = New-Object System.Drawing.Size(75, 23)
$selectFolderButton.Text = "Select Folder"
$form.Controls.Add($listBox) | Out-Null
$form.Controls.Add($okButton) | Out-Null
$form.Controls.Add($cancelButton) | Out-Null
$form.Controls.Add($selectFolderButton) | 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 Select Folder button click
$selectFolderButton.Add_Click({
$form.Tag = $listBox.SelectedItem + "|SELECT" # Add a flag to indicate folder selection
$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.Split('|')[0]}
# Check if the "Select Folder" button was clicked
if ($form.Tag -like "*|SELECT") {
return $selected # Return the selected folder
}
# If a folder is selected, browse into it
elseif ($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
}
}
function Connect-SharePoint {
return Connect-Graph
}
function List-XlsFiles {
try {
# Clear the DataGridView before listing new files
$script:dataGridView.Rows.Clear()
$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, but replace + with %20 for spaces
$encodedPath = [System.Web.HttpUtility]::UrlEncode($relativePath).Replace("+", "%20")
$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
# Call the recursive function to process files and subfolders
if ($script:chkRecursive.Checked) {
$script:txtStatus.Text += "Listing files recursively...`n"
$fileList = Get-XlsFilesRecursive -DriveId $drive.Id -DriveItemId $folderItem.id
} else {
$script:txtStatus.Text += "Listing files in current folder only...`n"
$fileList = Get-XlsFilesCurrentFolder -DriveId $drive.Id -DriveItemId $folderItem.id
}
} else {
$script:txtStatus.Text += "Searching in root folder`n"
if ($script:chkRecursive.Checked) {
$script:txtStatus.Text += "Listing files recursively...`n"
$fileList = Get-XlsFilesRecursive -DriveId $drive.Id -DriveItemId $root.Id
} else {
$script:txtStatus.Text += "Listing files in current folder only...`n"
$fileList = Get-XlsFilesCurrentFolder -DriveId $drive.Id -DriveItemId $root.Id
}
}
if ($fileList.Count -gt 0) {
$script:txtStatus.Text += "Saving file list...`n"
# Display each file on a new line
foreach ($file in $fileList) {
$row = @($file.OriginalPath, $file.OriginalFileName, $file.TempPath)
$script:dataGridView.Rows.Add($row)
}
#$fileList | ForEach-Object {
# $script:txtStatus.Text += "$($_.OriginalFileName)`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"
}
}
# Recursive function to get XLS files from a folder and its subfolders
function Get-XlsFilesRecursive {
param (
[string]$DriveId,
[string]$DriveItemId
)
$allFiles = @()
# Check if DriveId or DriveItemId is null or empty
if ([string]::IsNullOrEmpty($DriveId)) {
$script:txtStatus.Text += "Error: DriveId is null or empty`n"
return $allFiles
}
if ([string]::IsNullOrEmpty($DriveItemId)) {
$script:txtStatus.Text += "Error: DriveItemId is null or empty`n"
return $allFiles
}
# Get items in the current folder
try {
$items = Get-MgDriveItemChild -DriveId $DriveId -DriveItemId $DriveItemId -ErrorAction Stop
}
catch {
$script:txtStatus.Text += "Error getting items: $($_.Exception.Message)`n"
return $allFiles
}
foreach ($item in $items) {
$script:txtStatus.Text += "Checking item: $($item.Name)`n"
# If it's a folder, recurse into it
if ($item.Folder -and $item.Folder.ChildCount -ne $null) { # Check if it's a folder AND has children
$script:txtStatus.Text += "Found folder: $($item.Name), recursing...`n"
$allFiles += Get-XlsFilesRecursive -DriveId $DriveId -DriveItemId $item.Id
}
# If it's an Excel file, add it to the list
elseif ($item.Name -like "*.xls" -or $item.Name -like "*.xlsx" -or $item.Name -like "*.xlsm") {
$script:txtStatus.Text += "Found XLS file: $($item.Name)`n"
$allFiles += [PSCustomObject]@{
OriginalPath = $item.WebUrl
OriginalFileName = $item.Name
TempPath = "$($script:txtTempLib.Text)/$($item.Name)"
}
}
}
return $allFiles
}
# Function to get XLS files from only the current folder
function Get-XlsFilesCurrentFolder {
param (
[string]$DriveId,
[string]$DriveItemId
)
$allFiles = @()
# Check if DriveId or DriveItemId is null or empty
if ([string]::IsNullOrEmpty($DriveId)) {
$script:txtStatus.Text += "Error: DriveId is null or empty`n"
return $allFiles
}
if ([string]::IsNullOrEmpty($DriveItemId)) {
$script:txtStatus.Text += "Error: DriveItemId is null or empty`n"
return $allFiles
}
# Get items in the current folder
try {
$items = Get-MgDriveItemChild -DriveId $DriveId -DriveItemId $DriveItemId -ErrorAction Stop
}
catch {
$script:txtStatus.Text += "Error getting items: $($_.Exception.Message)`n"
return $allFiles
}
foreach ($item in $items) {
$script:txtStatus.Text += "Checking item: $($item.Name)`n"
# If it's an Excel file, add it to the list
if ($item.Name -like "*.xls" -or $item.Name -like "*.xlsx" -or $item.Name -like "*.xlsm") {
$script:txtStatus.Text += "Found XLS file: $($item.Name)`n"
$allFiles += [PSCustomObject]@{
OriginalPath = $item.WebUrl
OriginalFileName = $item.Name
TempPath = "$($script:txtTempLib.Text)/$($item.Name)"
}
}
}
return $allFiles
}
function Convert-Files {
$script:txtStatus.Text += "Convert-Files function called (placeholder).`n"
}