我想更改由下面的代码生成的XLSX文件的方向。
在excel软件中,我们可以这样做:
MSDN说我们可以通过Alignment.ReadingOrder执行此操作,但我如何使用它?
以下代码获取一组数据并制作excel文件。
public class ExcelHelper
{
public class ExcelData
{
public string SheetName { get; set; }
public List<string> Headers { get; set; }
public List<List<string>> Rows { get; set; }
}
public static byte[] GenerateExcel(ExcelData data)
{
var memoryStream = new MemoryStream();
var spreadsheetDocument = SpreadsheetDocument.Create(memoryStream, SpreadsheetDocumentType.Workbook);
var workbookPart = spreadsheetDocument.AddWorkbookPart();
workbookPart.Workbook = new Workbook();
var worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
var sheetData = new SheetData();
worksheetPart.Worksheet = new Worksheet(sheetData);
var sheets = spreadsheetDocument.WorkbookPart.Workbook.AppendChild<Sheets>(new Sheets());
var sheet = new Sheet()
{
Id = spreadsheetDocument.WorkbookPart.GetIdOfPart(worksheetPart),
SheetId = 1,
Name = data.SheetName ?? "Sheet 1",
};
sheets.AppendChild(sheet);
//--------------------------------
UInt32 rowIndex = 0;
//-------------------------------- header
var rowHeader = new Row { RowIndex = ++rowIndex };
foreach (var header in data.Headers)
{
var cell = new Cell
{
DataType = CellValues.InlineString,
//CellReference = header + rowIndex
};
var inlineString = new InlineString();
var text = new Text { Text = header ?? string.Empty };
inlineString.AppendChild(text);
cell.AppendChild(inlineString);
rowHeader.AppendChild(cell);
}
sheetData.AppendChild(rowHeader);
//-------------------------------- data
foreach (var row in data.Rows)
{
var rowData = new Row { RowIndex = ++rowIndex };
foreach (var cellData in row)
{
var cell = new Cell
{
DataType = CellValues.InlineString,
//CellReference = cellData + rowIndex
};
var inlineString = new InlineString();
var text = new Text { Text = cellData ?? string.Empty };
inlineString.AppendChild(text);
cell.AppendChild(inlineString);
rowData.AppendChild(cell);
}
sheetData.AppendChild(rowData);
}
workbookPart.Workbook.Save();
spreadsheetDocument.Close();
var bytes = memoryStream.ToArray();
memoryStream.Dispose();
return bytes;
}
}
答案 0 :(得分:0)
我通过技巧解决了问题;)
最佳做法是在MS Office Excel中手动创建模板文件,然后按代码打开它,并使用正确的数据填充目标单元格。
public class ExcelHelper
{
public static MemoryStream TemplateFile { get; set; }
public static MemoryStream TemplateFileEn { get; set; }
private static string[] ColumnsNames = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };
//todo: change
private const string TemplateFilePath =
@"\App_Data\TemplateFiles\Fax-ArchiveReport.xlsx";
private const string TemplateFileEnPath =
@"\App_Data\TemplateFiles\Fax-ArchiveReport-en.xlsx";
public class ExcelData
{
public string SheetName { get; set; }
public List<string> Headers { get; set; }
public List<List<string>> Rows { get; set; }
public bool IsEn { get; set; }
public string Title { get; set; }
}
public static byte[] GenerateExcelV2(ExcelData data)
{
try
{
var root = HttpContext.Current.Server.MapPath("~");
using( MemoryStream file = new MemoryStream() )
{
if (data.IsEn)
{
if (TemplateFileEn == null)
{
TemplateFileEn = new MemoryStream();
using (var stream = File.Open(root + TemplateFileEnPath, FileMode.Open))
{
stream.CopyTo(TemplateFileEn);
}
}
TemplateFileEn.Position = 0;
TemplateFileEn.CopyTo(file);
}
else
{
if (TemplateFile == null)
{
TemplateFile = new MemoryStream();
using (var stream = File.Open(root + TemplateFilePath, FileMode.Open))
{
stream.CopyTo(TemplateFile);
}
}
TemplateFile.Position = 0;
TemplateFile.CopyTo(file);
}
var result = UpdateCells(file, data.Title, data.Headers, data.Rows);
}
return result;
}
catch (Exception exception)
{
//todo: log in db
}
return null;
}
public static byte[] UpdateCells(MemoryStream doc, string title, List<string> headers, List<List<string>> rows)
{
// Open the document for editing.
SpreadsheetDocument spreadSheet = SpreadsheetDocument.Open(doc, true);
WorksheetPart worksheetPart = GetWorksheetPartByName(spreadSheet, "Fax-ArchiveReport");
if (worksheetPart != null)
{
//----------------------------------------------- title
Cell cellTitle = GetCell(worksheetPart.Worksheet, ColumnsNames[0], 2);
var inlineStringTitle = new InlineString();
inlineStringTitle.AppendChild(new Text { Text = title ?? string.Empty });
cellTitle.AppendChild(inlineStringTitle);
cellTitle.DataType = new EnumValue<CellValues>(CellValues.InlineString);
//----------------------------------------------- data
uint rowIndex = 4;
foreach (var row in rows)
{
uint rowCellIndex = 0;
foreach (var rowCell in row)
{
Cell cell = GetCell(worksheetPart.Worksheet, ColumnsNames[rowCellIndex], rowIndex);
var inlineStringRowCell = new InlineString();
inlineStringRowCell.AppendChild(new Text { Text = rowCell ?? string.Empty });
cell.AppendChild(inlineStringRowCell);
cell.DataType = new EnumValue<CellValues>(CellValues.InlineString);
rowCellIndex++;
}
rowIndex++;
}
//-----------------------------------------------
worksheetPart.Worksheet.Save();
spreadSheet.Close();
var bytes = doc.ToArray();
doc.Dispose();
return bytes;
}
return null;
}
private 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;
WorksheetPart worksheetPart = (WorksheetPart)document.WorkbookPart.GetPartById(relationshipId);
return worksheetPart;
}
// Given a worksheet, a column name, and a row index,
// gets the cell at the specified column and
private static Cell GetCell(Worksheet worksheet, string columnName, uint rowIndex)
{
Row row = GetRow(worksheet, rowIndex);
if (row == null)
return null;
return
row.Elements<Cell>()
.Where(c => string.Compare(c.CellReference.Value, columnName + rowIndex, true) == 0)
.First();
}
// Given a worksheet and a row index, return the row.
private static Row GetRow(Worksheet worksheet, uint rowIndex)
{
return worksheet.GetFirstChild<SheetData>().
Elements<Row>().Where(r => r.RowIndex == rowIndex).First();
}
}