Coverting Publisher documents so they are still editable

SaschaMac 0 Reputation points
2026-07-13T10:36:26.6233333+00:00

I know similar questions to this have been asked many times but I am still struggling. I have hundreds (if not thousands) of Publisher documents that I need to keep - converting to PDF is not an option as I want them to be completely editable afterwards. I was hoping there was an easy way to copy over to Powerpoint but I haven't found one so far. Word is not an option as I have many graphics and text boxes on all documents. Please, please, please if anyone can help as I have spent years building up these resources and don't want to lose them come October.

Microsoft 365 and Office | Publisher | For education

2 answers

Sort by: Newest
  1. Sarah 0 Reputation points
    2026-08-06T02:25:53.0966667+00:00
    • @Anonymous I
    • The instructions you provided worked great in converting to Microsoft Power Point, but all the words were in some kind of code or something, nothing related to what it should have said. Do you have any suggestions on how to fix that?

    Was this answer helpful?

    0 comments No comments

  2. Anonymous
    2026-07-13T12:47:29.23+00:00

    Hi @SaschaMac

    Based on my research and testing, I updated the script referenced in the following article: Microsoft Publisher will no longer be supported after October 2026 | Microsoft Support 

    The updated version converts Publisher files to PowerPoint (.pptx) format instead of PDF. 

    Here is the full PowerShell script that you can save as a .ps1 file:

    param
    (
    	[ValidateNotNullOrEmpty()]
    	[string]
    	$Filter,
     
    	[switch]
    	$Recurse
    )
     
    if (-not $PSBoundParameters.ContainsKey('Filter')) {
    	Write-Error "The -Filter parameter is required."
    	exit 1
    }
     
    if (-not ($Filter -like "*.pub")) {
    	Write-Error "The filter must specify .pub files (e.g., '*.pub' or 'file.pub').";
    	exit 1;
    }
     
    # Clean out any completely dead or frozen background instances before launching the engine
    Get-Process -Name "powerpnt" -ErrorAction SilentlyContinue | Stop-Process -Force
    Start-Sleep -Seconds 1
     
    try {
    	$files = Get-ChildItem $Filter -File -Recurse:$Recurse;
    	if (-not $files) {
    		Write-Error "No Publisher files found for the filter: $Filter";
    		exit 1;
    	}
     
    	Write-Output "Running vector element extraction..."
     
    	# Add Office and application Interop assemblies
    	Add-type -AssemblyName Office;
    	Add-type -AssemblyName Microsoft.Office.Interop.Publisher;
    	try {
    		$app = New-Object -ComObject Publisher.Application;
    		# Capture a snapshot of running instances before starting
    		$existingPids = (Get-Process -Name "powerpnt" -ErrorAction SilentlyContinue).Id
    		# Spin up PowerPoint and ensure window references attach cleanly
    		$pptApp = New-Object -ComObject PowerPoint.Application;
    		$pptApp.Visible = [Microsoft.Office.Core.MsoTriState]::msoTrue
    		# Isolate the exact PID of the COM instance we just created
    		Start-Sleep -Milliseconds 500
    		$currentPids = (Get-Process -Name "powerpnt" -ErrorAction SilentlyContinue).Id
    		$pptPid = $currentPids | Where-Object { $_ -notin $existingPids } | Select-Object -First 1
    		# If it's a single global instance fallback, grab the active running PID safely
    		if (-not $pptPid) {
    			$pptPid = (Get-Process -Name "powerpnt" | Sort-Object StartTime -Descending | Select-Object -First 1).Id
    		}
    	} catch {
    		Write-Error "Microsoft Publisher or PowerPoint is not installed or accessible."
    		exit 1;
    	}
     
    	$successCount = 0;
    	$failCount = 0;
     
    	foreach ($file in $files) {
    		if ($file.Extension -eq ".pub") {
    			$fileFullName = $file.FullName;
    			$pptxFilePath = [System.IO.Path]::ChangeExtension($fileFullName, '.pptx')
    			if (Test-Path $pptxFilePath) {
    				Write-Output "Existing PowerPoint file found. Removing: $pptxFilePath"
    				Remove-Item $pptxFilePath -Force -ErrorAction SilentlyContinue
    			}
     
    			try {
    				$doc = $app.Open($fileFullName);
    			} catch {
    				$failCount++;
    				Write-Error "Error opening file: $fileFullName $_";
    				Continue;
    			}
     
    			if (-not($doc)) {
    				$failCount++;
    				Write-Error "Failed to open file: $fileFullName";
    				Continue;
    			}
     
    			try {
    				$presentation = $pptApp.Presentations.Add([Microsoft.Office.Core.MsoTriState]::msoTrue);
    				$pageSetup = $doc.PageSetup;
    				if ($null -ne $pageSetup) {
    					try {
    						$presentation.PageSetup.SlideWidth = $pageSetup.PageWidth;
    						$presentation.PageSetup.SlideHeight = $pageSetup.PageHeight;
    					} catch {
    						$presentation.PageSetup.SlideWidth = 960;  
    						$presentation.PageSetup.SlideHeight = 540; 
    					}
    				} else {
    					$presentation.PageSetup.SlideWidth = 960;
    					$presentation.PageSetup.SlideHeight = 540;
    				}
     
    				foreach ($pubPage in $doc.Pages) {
    					$slide = $presentation.Slides.Add($presentation.Slides.Count + 1, [Microsoft.Office.Interop.PowerPoint.PpSlideLayout]::ppLayoutBlank);
    					if ($pubPage.Shapes.Count -gt 0) {
    						try {
    							$tempMetaPath = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), "pub_vector_$($pubPage.PageNumber)_$([Guid]::NewGuid().ToString().Substring(0,8)).emf")
    							$pubPage.SaveAsPicture($tempMetaPath, [Microsoft.Office.Interop.Publisher.PbPictureResolution]::pbPictureResolutionCommercialPrint_300DPI)
    							if (Test-Path $tempMetaPath) {
    								$vectorShape = $slide.Shapes.AddPicture($tempMetaPath, [Microsoft.Office.Core.MsoTriState]::msoFalse, [Microsoft.Office.Core.MsoTriState]::msoTrue, 0, 0, $presentation.PageSetup.SlideWidth, $presentation.PageSetup.SlideHeight)
    								try {
    									$ungroupedShapes = $vectorShape.Ungroup()
    									if ($null -ne $ungroupedShapes) {
    										foreach ($sh in $ungroupedShapes) {
    											if ($sh.Type -eq [Microsoft.Office.Core.MsoShapeType]::msoGroup) {
    												try { $sh.Ungroup() | Out-Null } catch {}
    											}
    										}
    									}
    								} catch {}
    								Remove-Item $tempMetaPath -Force -ErrorAction SilentlyContinue
    							}
    						} catch {
    							Write-Error "Error converting layout on page $($pubPage.PageNumber): $_"
    						}
    					}
    				}
     
    				if ($presentation.Slides.Count -gt 1 -and $presentation.Slides.Item(1).Shapes.Count -eq 0) {
    					$presentation.Slides.Item(1).Delete()
    				}
     
    				$presentation.SaveAs($pptxFilePath, [Microsoft.Office.Interop.PowerPoint.PpSaveAsFileType]::ppSaveAsOpenXMLPresentation);
    				if (Test-Path $pptxFilePath) {
    					Write-Output "Exported safely to $pptxFilePath.";
    					$successCount++;
    				} else {
    					$failCount++;
    					Write-Error "Failed to export file: $fileFullName";
    				}
    				$presentation.Close();
    			} catch {
    				$failCount++;
    				Write-Error "Error during PowerPoint structure migration: $_";
    				if ($presentation) { 
    					try { $presentation.Close(); } catch {}
    				}
    			}
     
    			try { $doc.Close(); } catch {}
    		}
    	}
     
    	Write-Output "Converted $successCount files with $failCount errors.";
    } catch {
    	Write-Error $_;
    } finally {
    	# Standard programmatic close call
    	try { if ($doc) { $doc.Close(); } } catch {}
    	try { if ($presentation) { $presentation.Close(); } } catch {}
    	try { if ($app) { $app.Quit(); } } catch {}
    	try { if ($pptApp) { $pptApp.Quit(); } } catch {}
     
    	# Break COM object plumbing links in the environment
    	[System.Runtime.InteropServices.Marshal]::ReleaseComObject($app) | Out-Null
    	[System.Runtime.InteropServices.Marshal]::ReleaseComObject($pptApp) | Out-Null
    	[GC]::Collect()
    	[GC]::WaitForPendingFinalizers()
    	Start-Sleep -Seconds 1
     
    	# Target and force kill the specific tracked process ID 
    	if ($pptPid) {
    		Write-Output "Targeting specific PowerPoint process handle (PID: $pptPid) for closure..."
    		Get-Process -Id $pptPid -ErrorAction SilentlyContinue | Stop-Process -Force
    		Write-Output "PowerPoint window and process successfully closed."
    	}
    }
    

     

    Throughout my testing, I was able to convert the sample .pub file to a .pptx file, and it remained editable after the conversion.

    You can run the script by following these steps: 

    Step 1: Open PowerShell with administrator permissions. 

    Step 2: Navigate to the folder containing the PowerShell script. 

    For example: 

    cd "C:\Users\Documents" 
    

    Step 3: Convert a specific Publisher file to .pptx using a command similar to the example below: 

     .\<NameofScript>.ps1 -Filter "C:\Users\Documents\MyFile.pub" 
    

    Step 4: Wait for the script to complete, then review the resulting PowerPoint file to determine whether it meets your editing requirements. 

    If the results meet your expectations, you can also process all Publisher files within a directory using: 

    .\<NameofScript>.ps1 -Filter "C:\Users\Documents\*.pub" 
    

     

    I hope this provides some additional insight. 


    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    Was this answer helpful?


Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.