# 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 { 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 { $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 } 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" } }