I know it's a long time since last post in the topic, but I was recently dealing with this problem and I found that way to get what I wanted (EPPlus v4.5.3):
public static void FreezeHeader(ExcelWorksheet sheet)
{
var xdoc = sheet.WorksheetXml;
var sheetViews = xdoc.GetElementsByTagName("sheetViews");
var sheetViewNode = sheetViews[0].ChildNodes[0];
var paneNode = xdoc.CreateNode(System.Xml.XmlNodeType.Element, "pane", xdoc.DocumentElement.NamespaceURI);
var ySplit = xdoc.CreateAttribute("ySplit");
ySplit.Value = "1";
var topLeftCell = xdoc.CreateAttribute("topLeftCell");
topLeftCell.Value = "A2";
var activePane = xdoc.CreateAttribute("activePane");
activePane.Value = "bottomLeft";
var state = xdoc.CreateAttribute("state");
state.Value = "frozen";
paneNode.Attributes.Append(ySplit);
paneNode.Attributes.Append(topLeftCell);
paneNode.Attributes.Append(activePane);
paneNode.Attributes.Append(state);
sheetViewNode.AppendChild(paneNode);
}
I achieved this by comparing the xml of two Excel files (one with freezed header and another witouht).
Typically when creating a simple excel file, you get the following :
<sheetViews>
<sheetView workbookViewId="0">
</sheetView>
</sheetViews>
Now if you freeze the first row and examine the xml, you will see that :
<sheetViews>
<sheetView tabSelected="1" topLeftCell="Z1" zoomScale="85" zoomScaleNormal="85" workbookViewId="0">
<pane ySplit="1" topLeftCell="A213" activePane="bottomLeft" state="frozen"/>
<selection activeCell="O1" sqref="O1"/><selection pane="bottomLeft" activeCell="AD229" sqref="AD229"/>
</sheetView>
From that I deduced I had to add the "pane" node to the xml structue:
<pane ySplit="1" topLeftCell="A213" activePane="bottomLeft" state="frozen"/>
That's what the code I provide is doing :-)