#c# #image #excel #openxml
#c# #изображение #excel #openxml
Вопрос:
Я использую модифицированную версию этого кода для создания документа Excel, добавления ячеек и оформления ячеек. Я пытаюсь изменить этот код, чтобы также иметь возможность добавлять изображения на лист. Я ничего не добиваюсь, и в Интернете действительно нет ничего, что могло бы помочь. Я пытаюсь прочитать разницу в инструменте повышения производительности OpenXML. что отчасти бесполезно. Кто-нибудь здесь может указать мне правильное направление?
Спасибо.
Ответ №1:
Я просмотрел ответы Винсента Тана и Дэвида Йейтса. Поскольку мне потребовались часы кодирования, чтобы выполнить следующие простые требования, я опубликую свое решение здесь, чтобы следующий пользователь мог сэкономить немного времени.
Требования:
- Добавьте изображение в определенную ячейку существующей электронной таблицы Excel
- Создайте новую электронную таблицу и добавьте изображение в определенную ячейку
- Добавьте изображение в определенную ячейку WorksheetPart (чтобы перед его сохранением можно было выполнить другие операции)
- Добавьте изображение из потока
- Добавьте изображение из файла
- Используйте разные форматы изображений
Использование
// Add via file to existing spreadsheet
try
{
ExcelTools.AddImage(false, filePath, "Sheet name",
imagePath, "Image description",
2 /* column */, 2 /* row */);
}
catch ...
// Add via stream to existing spreadsheet
try
{
ExcelTools.AddImage(false, filePath, "Sheet name",
imageStream, "Image description",
2 /* column */, 2 /* row */);
}
catch ...
// Create spreadsheet and add image via path
try
{
ExcelTools.AddImage(true, filePath, "Sheet name",
imagePath, "Image description",
2 /* column */, 2 /* row */);
}
catch ...
// Create spreadsheet and add image via stream
try
{
ExcelTools.AddImage(true, filePath, "Sheet name",
imageStream, "Image description",
2 /* column */, 2 /* row */);
}
catch ...
// Add multiple images or apply further changes
try
{
// Open spreadsheet
spreadsheetDocument = SpreadsheetDocument.Open(excelFile, true);
// Get WorksheetPart
worksheetPart = ExcelTools.GetWorksheetPartByName(spreadsheetDocument, "Some sheet name");
AddImage(worksheetPart, imagePath1, "My first image", 1, 1); // A1
AddImage(worksheetPart, imagePath2, "My second image", 1, 5); // A5
AddImage(worksheetPart, imagePath3, "My third image", 2, 7); // B7
// Other operations if needed
worksheetPart.Worksheet.Save();
spreadsheetDocument.Close();
}
catch ...
Код:
using System;
using System.Data;
using System.Linq;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using System.Collections.Generic;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using A = DocumentFormat.OpenXml.Drawing;
using Xdr = DocumentFormat.OpenXml.Drawing.Spreadsheet;
namespace Utilities
{
public class ExcelTools
{
public static ImagePartType GetImagePartTypeByBitmap(Bitmap image)
{
if (ImageFormat.Bmp.Equals(image.RawFormat))
return ImagePartType.Bmp;
else if (ImageFormat.Gif.Equals(image.RawFormat))
return ImagePartType.Gif;
else if (ImageFormat.Png.Equals(image.RawFormat))
return ImagePartType.Png;
else if (ImageFormat.Tiff.Equals(image.RawFormat))
return ImagePartType.Tiff;
else if (ImageFormat.Icon.Equals(image.RawFormat))
return ImagePartType.Icon;
else if (ImageFormat.Jpeg.Equals(image.RawFormat))
return ImagePartType.Jpeg;
else if (ImageFormat.Emf.Equals(image.RawFormat))
return ImagePartType.Emf;
else if (ImageFormat.Wmf.Equals(image.RawFormat))
return ImagePartType.Wmf;
else
throw new Exception("Image type could not be determined.");
}
public static WorksheetPart GetWorksheetPartByName(SpreadsheetDocument document, string sheetName)
{
IEnumerable<Sheet> sheets =
document.WorkbookPart.Workbook.GetFirstChild<Sheets>().
Elements<Sheet>().Where(s => s.Name == sheetName);
if (sheets.Count() == 0)
{
// The specified worksheet does not exist
return null;
}
string relationshipId = sheets.First().Id.Value;
return (WorksheetPart)document.WorkbookPart.GetPartById(relationshipId);
}
public static void AddImage(bool createFile, string excelFile, string sheetName,
string imageFileName, string imgDesc,
int colNumber, int rowNumber)
{
using (var imageStream = new FileStream(imageFileName, FileMode.Open))
{
AddImage(createFile, excelFile, sheetName, imageStream, imgDesc, colNumber, rowNumber);
}
}
public static void AddImage(WorksheetPart worksheetPart,
string imageFileName, string imgDesc,
int colNumber, int rowNumber)
{
using (var imageStream = new FileStream(imageFileName, FileMode.Open))
{
AddImage(worksheetPart, imageStream, imgDesc, colNumber, rowNumber);
}
}
public static void AddImage(bool createFile, string excelFile, string sheetName,
Stream imageStream, string imgDesc,
int colNumber, int rowNumber)
{
SpreadsheetDocument spreadsheetDocument = null;
WorksheetPart worksheetPart = null;
if (createFile)
{
// Create a spreadsheet document by supplying the filepath
spreadsheetDocument = SpreadsheetDocument.Create(excelFile, SpreadsheetDocumentType.Workbook);
// Add a WorkbookPart to the document
WorkbookPart workbookpart = spreadsheetDocument.AddWorkbookPart();
workbookpart.Workbook = new Workbook();
// Add a WorksheetPart to the WorkbookPart
worksheetPart = workbookpart.AddNewPart<WorksheetPart>();
worksheetPart.Worksheet = new Worksheet(new SheetData());
// Add Sheets to the Workbook
Sheets sheets = spreadsheetDocument.WorkbookPart.Workbook.
AppendChild<Sheets>(new Sheets());
// Append a new worksheet and associate it with the workbook
Sheet sheet = new Sheet()
{
Id = spreadsheetDocument.WorkbookPart.GetIdOfPart(worksheetPart),
SheetId = 1,
Name = sheetName
};
sheets.Append(sheet);
}
else
{
// Open spreadsheet
spreadsheetDocument = SpreadsheetDocument.Open(excelFile, true);
// Get WorksheetPart
worksheetPart = GetWorksheetPartByName(spreadsheetDocument, sheetName);
}
AddImage(worksheetPart, imageStream, imgDesc, colNumber, rowNumber);
worksheetPart.Worksheet.Save();
spreadsheetDocument.Close();
}
public static void AddImage(WorksheetPart worksheetPart,
Stream imageStream, string imgDesc,
int colNumber, int rowNumber)
{
// We need the image stream more than once, thus we create a memory copy
MemoryStream imageMemStream = new MemoryStream();
imageStream.Position = 0;
imageStream.CopyTo(imageMemStream);
imageStream.Position = 0;
var drawingsPart = worksheetPart.DrawingsPart;
if (drawingsPart == null)
drawingsPart = worksheetPart.AddNewPart<DrawingsPart>();
if (!worksheetPart.Worksheet.ChildElements.OfType<Drawing>().Any())
{
worksheetPart.Worksheet.Append(new Drawing { Id = worksheetPart.GetIdOfPart(drawingsPart) });
}
if (drawingsPart.WorksheetDrawing == null)
{
drawingsPart.WorksheetDrawing = new Xdr.WorksheetDrawing();
}
var worksheetDrawing = drawingsPart.WorksheetDrawing;
Bitmap bm = new Bitmap(imageMemStream);
var imagePart = drawingsPart.AddImagePart(GetImagePartTypeByBitmap(bm));
imagePart.FeedData(imageStream);
A.Extents extents = new A.Extents();
var extentsCx = bm.Width * (long)(914400 / bm.HorizontalResolution);
var extentsCy = bm.Height * (long)(914400 / bm.VerticalResolution);
bm.Dispose();
var colOffset = 0;
var rowOffset = 0;
var nvps = worksheetDrawing.Descendants<Xdr.NonVisualDrawingProperties>();
var nvpId = nvps.Count() > 0
? (UInt32Value)worksheetDrawing.Descendants<Xdr.NonVisualDrawingProperties>().Max(p => p.Id.Value) 1
: 1U;
var oneCellAnchor = new Xdr.OneCellAnchor(
new Xdr.FromMarker
{
ColumnId = new Xdr.ColumnId((colNumber - 1).ToString()),
RowId = new Xdr.RowId((rowNumber - 1).ToString()),
ColumnOffset = new Xdr.ColumnOffset(colOffset.ToString()),
RowOffset = new Xdr.RowOffset(rowOffset.ToString())
},
new Xdr.Extent { Cx = extentsCx, Cy = extentsCy },
new Xdr.Picture(
new Xdr.NonVisualPictureProperties(
new Xdr.NonVisualDrawingProperties { Id = nvpId, Name = "Picture " nvpId, Description = imgDesc },
new Xdr.NonVisualPictureDrawingProperties(new A.PictureLocks { NoChangeAspect = true })
),
new Xdr.BlipFill(
new A.Blip { Embed = drawingsPart.GetIdOfPart(imagePart), CompressionState = A.BlipCompressionValues.Print },
new A.Stretch(new A.FillRectangle())
),
new Xdr.ShapeProperties(
new A.Transform2D(
new A.Offset { X = 0, Y = 0 },
new A.Extents { Cx = extentsCx, Cy = extentsCy }
),
new A.PresetGeometry { Preset = A.ShapeTypeValues.Rectangle }
)
),
new Xdr.ClientData()
);
worksheetDrawing.Append(oneCellAnchor);
}
}
}
Комментарии:
1. Я думаю, важно отметить, что вы используете even System. Рисунок здесь..
2. Извините, я не думаю, что понимаю, что вы имеете в виду. В чем смысл использования System. Рисование?
3. Я сделал это в .NET Core, и мне нужно добавить систему. Рисование. Общий пакет nuget для системы. Библиотека рисования
4. Ах, теперь я понял, понял. Возможно, удастся избежать System. Рисование вручную укажите тип, высоту и ширину изображения. Это код, который пришлось бы переписать: Bitmap bm = новое растровое изображение (imageMemStream); var ImagePart = drawingsPart.AddImagePart(GetImagePartTypeByBitmap(bm)); ImagePart.FeedData(ImageStream); A.Extents extents = новый A.Extents(); var extentsCx = bm.Width * (long)(914400 / bm.HorizontalResolution ); переменная extentsCy = bm. Высота * (длина) (914400 / bm.VerticalResolution); bm.Dispose();
5. Тогда GetImagePartTypeByBitmap (растровое изображение) можно было бы удалить.
Ответ №2:
Я написал кое-что об этом здесь, в сообщении в блоге: http://polymathprogrammer.com/2009/12/21/advanced-styling-in-excel-open-xml /
Обратите внимание, что изначально оно было написано для версии Open XML SDK 2.0 CTP, поэтому остерегайтесь перехода с класса NumberFormat на класс NumberingFormat (когда SDK 2.0 был завершен)
Если вы хотите выделить код только для вставки изображения, взгляните сюда: http://polymathprogrammer.com/2009/11/30/how-to-insert-an-image-in-excel-open-xml /
Комментарии:
1. Приведенные выше ссылки не работают
Ответ №3:
Вот ссылка на пример MSDN с кодом, который вы можете загрузить.
Также есть пример Эрика Уайта и видео на You Tube