Skip to content

Instantly share code, notes, and snippets.

@dgosbell
Created October 20, 2022 01:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dgosbell/76899cd8141f3989047d929a20d10411 to your computer and use it in GitHub Desktop.
Save dgosbell/76899cd8141f3989047d929a20d10411 to your computer and use it in GitHub Desktop.
Extract PowerQuery code directly from xlsx file
# Open the xlsx file and find the DataMashup item
$xlPkg = [System.IO.Packaging.Package]::Open($xlFile)
$itemParts = $xlPkg.GetParts() | where {$_.Uri -like "/customXml/item*" -and $_.ContentType -eq "application/xml"}
foreach ($p in $itemParts)
{
$itemStrm = $p.GetStream();
$itemRdr = [System.IO.StreamReader]::new($itemStrm)
$content = [xml]$itemRdr.ReadToEnd()
$base64 = $content["DataMashup"].InnerText
if ($base64 -ne $null) {break;}
}
$xlPkg.Close()
# quit here if we did not find any DataMashup content
if ($base64 -eq $null) { return }
# take the base64 mashup item and grab the length of the package parts content
# see https://learn.microsoft.com/en-us/openspecs/office_file_formats/ms-qdeff/22557f6d-7c29-4554-8fe4-7b7a54ac7a2b
$bytes = [System.Convert]::FromBase64String($base64)
$lenB = $bytes[4..7]
$len = [BitConverter]::ToInt32($lenb,0)
$Bytes2 = $bytes[8..($len+7)]
# then decompress the package parts content and extract the Section1.m file
$strm = [System.IO.MemoryStream]::new( $Bytes2)
$pkg = [System.IO.Packaging.Package]::Open($strm)
$part = $pkg.GetPart("/Formulas/Section1.m")
$strmPart = $part.GetStream()
$rdr = [System.IO.StreamReader]::new($strmPart)
$mcode = $rdr.ReadToEnd()
#display the M code
$mcode
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment