Epplus ライブラリにも同じ問題があります。
コードでこれを解決する方法が見つからなかった後、このライブラリのソースコードをチェックしました。Epplus は常にtwoCellAnchor
図面として Excel 画像を作成します。このコードでxlsx
見つけることができるファイルで:drawingXYZ.xml
<xdr:twoCellAnchor editAs="oneCell">
<xdr:from> ... </xdr:from>
<xdr:to> ... </xdr:to>
<xdr:pic>
...
</xdr:twoCellAnchor>
そのため、画像は常に 2 つのセルに接続されており、これは Epplus ライブラリの可変部分ではありません。コードのこの部分は、ExcelDrawing.csファイルにあります。
XmlElement drawNode = _drawingsXml.CreateElement(
"xdr", "twoCellAnchor", ExcelPackage.schemaSheetDrawings);
colNode.AppendChild(drawNode);
この dll の独自のコピーを簡単に作成できます。幸いなことに、この問題を修正するには、 2 つのファイルを変更するだけで済みます。そう..
このサイトから Epplus ライブラリのソース コードのコピーをダウンロードし、Visual Studio で開きます。
oneCellAnchordrawing
としてコードを生成する必要があるため、画像の要素を削除し、画像のサイズをパラメーターとして要素を作成する必要があります。
新しい xml 構造は次のようになります。<xdr:to>
<xdr:ext />
<xdr:oneCellAnchor editAs="oneCell">
<xdr:from> ... </xdr:from>
<xdr:ext cx="1234567" cy="7654321" />
<xdr:pic>
...
</xdr:oneCellAnchor>
わかりました、それで、これを行う方法は?
Epplusコードの変更
ExcelDrawings.cs (ファイルへのリンクはこちら)
- まず、
CreateDrawingXml()
内のメソッドを変更しExcelDrawings.cs
ます。元の機能を保持するためにoneCellAnchor
、デフォルト値を持つオプションのパラメーター ( create の場合) を追加します。メソッドでは、このパラメーターに基づいて、1 つまたは 2 つのセル アンカーを作成し、<xdr:to>
要素を作成するかどうかを指定します。
このメソッド コードの重要な部分:
private XmlElement CreateDrawingXml(bool twoCell = true) {
if (DrawingXml.OuterXml == "")
{ ... } // not changed
XmlNode colNode= _drawingsXml.SelectSingleNode("//xdr:wsDr", NameSpaceManager);
//First change in method code
XmlElement drawNode;
if (twoCell)
drawNode = _drawingsXml.CreateElement(
"xdr", "twoCellAnchor", ExcelPackage.schemaSheetDrawings);
else
drawNode = _drawingsXml.CreateElement(
"xdr", "oneCellAnchor", ExcelPackage.schemaSheetDrawings);
colNode.AppendChild(drawNode);
//Add from position Element; // Not changed
XmlElement fromNode = _drawingsXml.CreateElement(
"xdr", "from", ExcelPackage.schemaSheetDrawings);
drawNode.AppendChild(fromNode);
fromNode.InnerXml = "<xdr:col>0</xdr:col><xdr:colOff>0</xdr:colOff>"
+ "<xdr:row>0</xdr:row><xdr:rowOff>0</xdr:rowOff>";
//Add to position Element;
//Second change in method
if (twoCell)
{
XmlElement toNode = _drawingsXml.CreateElement(
"xdr", "to", ExcelPackage.schemaSheetDrawings);
drawNode.AppendChild(toNode);
toNode.InnerXml = "<xdr:col>10</xdr:col><xdr:colOff>0</xdr:colOff>"
+ "<xdr:row>10</xdr:row><xdr:rowOff>0</xdr:rowOff>";
}
return drawNode;
}
AddPicture
次に、同じファイル内の2 つのメソッドを変更します。
public ExcelPicture AddPicture(string Name, Image image, Uri Hyperlink)
{
if (image != null) {
if (_drawingNames.ContainsKey(Name.ToLower())) {
throw new Exception("Name already exists in the drawings collection");
}
XmlElement drawNode = CreateDrawingXml(false);
// Change: we need create element with dimensions
// like: <xdr:ext cx="3857625" cy="1047750" />
XmlElement xdrext = _drawingsXml.CreateElement(
"xdr", "ext", ExcelPackage.schemaSheetDrawings);
xdrext.SetAttribute("cx",
(image.Width * ExcelDrawing.EMU_PER_PIXEL).ToString());
xdrext.SetAttribute("cy",
(image.Height * ExcelDrawing.EMU_PER_PIXEL).ToString());
drawNode.AppendChild(xdrext);
// End of change, next part of method is the same:
drawNode.SetAttribute("editAs", "oneCell");
...
}
}
そして、このメソッドをFileInfo
入力パラメーターとして使用します。
public ExcelPicture AddPicture(string Name, FileInfo ImageFile, Uri Hyperlink)
{
if (ImageFile != null) {
if (_drawingNames.ContainsKey(Name.ToLower())) {
throw new Exception("Name already exists in the drawings collection");
}
XmlElement drawNode = CreateDrawingXml(false);
// Change: First create ExcelPicture object and calculate EMU dimensions
ExcelPicture pic = new ExcelPicture(this, drawNode, ImageFile, Hyperlink);
XmlElement xdrext = _drawingsXml.CreateElement(
"xdr", "ext", ExcelPackage.schemaSheetDrawings);
xdrext.SetAttribute("cx",
(pic.Image.Width * ExcelDrawing.EMU_PER_PIXEL).ToString());
xdrext.SetAttribute("cy",
(pic.Image.Height * ExcelDrawing.EMU_PER_PIXEL).ToString());
drawNode.AppendChild(xdrext);
// End of change, next part of method is the same (without create pic object)
drawNode.SetAttribute("editAs", "oneCell");
...
}
}
したがって、これはすべて重要なコードです。次に、ノードを検索するコードを変更し、要素の順序を保持する必要があります。
では、次のprivate void AddDrawings()
ように変更xpath
します。
XmlNodeList list = _drawingsXml.SelectNodes(
"//xdr:twoCellAnchor", NameSpaceManager);
これに:
XmlNodeList list = _drawingsXml.SelectNodes(
"//(xdr:twoCellAnchor or xdr:oneCellAnchor)", NameSpaceManager);
それはすべてこのファイルにあります。今度は
ExcelPicture.cs (ファイルへのリンクはこちら)を変更します。
元のコードは、次のようにコンストラクターに次のコードを追加するためのノードを検索します。
node.SelectSingleNode("xdr:to",NameSpaceManager);
常に要素を作成するわけではないため<xdr:to>
、次のコードを変更します。
internal ExcelPicture(ExcelDrawings drawings, XmlNode node
, Image image, Uri hyperlink)
: base(drawings, node, "xdr:pic/xdr:nvPicPr/xdr:cNvPr/@name")
{
XmlElement picNode = node.OwnerDocument.CreateElement(
"xdr", "pic", ExcelPackage.schemaSheetDrawings);
// Edited: find xdr:to, or xdr:ext if xdr:to not exists
XmlNode befor = node.SelectSingleNode("xdr:to",NameSpaceManager);
if (befor != null && befor.Name == "xdr:to")
node.InsertAfter(picNode, befor);
else {
befor = node.SelectSingleNode("xdr:ext", NameSpaceManager);
node.InsertAfter(picNode, befor);
}
// End of change, next part of constructor is unchanged
_hyperlink = hyperlink;
...
}
入力パラメーターとして FileInfo を使用する 2 番目のコンストラクターについても同じです。
internal ExcelPicture(ExcelDrawings drawings, XmlNode node
, FileInfo imageFile, Uri hyperlink)
: base(drawings, node, "xdr:pic/xdr:nvPicPr/xdr:cNvPr/@name")
{
XmlElement picNode = node.OwnerDocument.CreateElement(
"xdr", "pic", ExcelPackage.schemaSheetDrawings);
// Edited: find xdr:to, or xdr:ext if xdr:to not exists
XmlNode befor = node.SelectSingleNode("xdr:to", NameSpaceManager);
if (befor != null && befor.Name == "xdr:to")
node.InsertAfter(picNode, befor);
else {
befor = node.SelectSingleNode("xdr:ext", NameSpaceManager);
node.InsertAfter(picNode, befor);
}
// End of change, next part of constructor is unchanged
_hyperlink = hyperlink;
...
これで、写真は として作成されoneCellAnchor
ます。AddPicture
必要に応じて、ブース バリアント用に複数のメソッドを作成できます。最後のステップは、このプロジェクトをビルドし、独自のカスタム を作成することEPPlus.dll
です。次に、この dll を使用するプロジェクトを閉じて、プロジェクト内の同じ場所に新しいファイルEPPlus.dll
、EPPlus.pdb
、をコピーEPPlus.XML
します (元の dll ファイルをバックアップして置き換えます) (したがって、プロジェクトの参照や設定を変更する必要はありません)。
次に、プロジェクトを開いて再構築し、これで問題が解決するかどうか試してください。