Forum Discussion
Modifying the Layout file that is embedded in a pbix file
- Anonymous5 years ago
I was struggling with this issue recently, and my solution is the following:
- Change the extension from ".pbix" to ".zip"
- Do not unzip the ".zip" file during this process
- Extract the "Layout" file from the "Report" folder in the ".zip" file
- Open the "Layout" file with Notepad++. (VERY IMPORTANT)
- Make your modifications in the Layout file
- Substitute the old "Layout" file with the new one
- Delete "SecurityBindings" file in the ".zip" file
- In the [Contents_type].xml delete the following text:
"<Override PartName="/SecurityBindings" ContentType="" />"
- Change the extension from ".zip to ".pbix"
- The file will open without breaks
Hope it helps!
I found that when I was saving, the WriteAllTextAsync was prepending 2 extra bytes.. using FlexHex I could see that the original did not have that.
To fix this I just saved with WriteAllTextAsync with Encoding.Unicode. Re-opened as bytes and saved skipping the first 2 bytes in question.
var serializedFile = JsonConvert.SerializeObject(_layoutModel);
await System.IO.File.WriteAllTextAsync(Filepath, serializedFile, Encoding.Unicode);
var asBytes = await System.IO.File.ReadAllBytesAsync(Filepath);
await System.IO.File.WriteAllBytesAsync(Filepath, asBytes.Skip(2).ToArray());
Just as an FYI, as others have mentioned I also needed to edit [Content_Type].xml and remove the Override tag with the PartName == "/SecurityBindings". After that powerbi loaded it fine (ignoring the validation checks it did).
After a little research I found that it's a marker for byte order of unicode (I'd gussed it was this, but didn't know for sure until now). Anyway, I've update the code pushed here yesterday. (Couldn't find an edit link for my previous post)
public async Task Save()
{
var layoutFile = JsonConvert.SerializeObject(_layoutModel);
await System.IO.File.WriteAllTextAsync(Filepath, layoutFile, Encoding.Unicode);
IEnumerable<byte> layoutAsBytes = await System.IO.File.ReadAllBytesAsync(Filepath);
layoutAsBytes = StripUnicodeByteOrder(layoutAsBytes);
await System.IO.File.WriteAllBytesAsync(Filepath, layoutAsBytes.ToArray());
}
public static IEnumerable<Byte> StripUnicodeByteOrder(IEnumerable<byte> bytes)
{
if (bytes.ElementAt(0) == 0xFF && bytes.ElementAt(1) == 0xFE)
bytes = bytes.Skip(2);
return bytes;
}