-
Notifications
You must be signed in to change notification settings - Fork 813
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move saving of a workbook part from XLWorkbook_Save to a separate wri…
…ter.
- Loading branch information
Showing
2 changed files
with
366 additions
and
371 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,365 @@ | ||
#nullable disable | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using ClosedXML.Utils; | ||
using DocumentFormat.OpenXml; | ||
using DocumentFormat.OpenXml.Packaging; | ||
using DocumentFormat.OpenXml.Spreadsheet; | ||
|
||
namespace ClosedXML.Excel.IO | ||
{ | ||
internal class WorkbookPartWriter | ||
{ | ||
internal static void GenerateContent(WorkbookPart workbookPart, XLWorkbook xlWorkbook, SaveOptions options, XLWorkbook.SaveContext context) | ||
{ | ||
if (workbookPart.Workbook == null) | ||
workbookPart.Workbook = new Workbook(); | ||
|
||
var workbook = workbookPart.Workbook; | ||
if ( | ||
!workbook.NamespaceDeclarations.Contains(new KeyValuePair<string, string>("r", | ||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships"))) | ||
{ | ||
workbook.AddNamespaceDeclaration("r", | ||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships"); | ||
} | ||
|
||
#region WorkbookProperties | ||
|
||
if (workbook.WorkbookProperties == null) | ||
workbook.WorkbookProperties = new WorkbookProperties(); | ||
|
||
if (workbook.WorkbookProperties.CodeName == null) | ||
workbook.WorkbookProperties.CodeName = "ThisWorkbook"; | ||
|
||
workbook.WorkbookProperties.Date1904 = OpenXmlHelper.GetBooleanValue(xlWorkbook.Use1904DateSystem, false); | ||
|
||
if (options.FilterPrivacy.HasValue) | ||
workbook.WorkbookProperties.FilterPrivacy = OpenXmlHelper.GetBooleanValue(options.FilterPrivacy.Value, false); | ||
|
||
#endregion WorkbookProperties | ||
|
||
#region FileSharing | ||
|
||
if (workbook.FileSharing == null) | ||
workbook.FileSharing = new FileSharing(); | ||
|
||
workbook.FileSharing.ReadOnlyRecommended = OpenXmlHelper.GetBooleanValue(xlWorkbook.FileSharing.ReadOnlyRecommended, false); | ||
workbook.FileSharing.UserName = String.IsNullOrWhiteSpace(xlWorkbook.FileSharing.UserName) ? null : StringValue.FromString(xlWorkbook.FileSharing.UserName); | ||
|
||
if (!workbook.FileSharing.HasChildren && !workbook.FileSharing.HasAttributes) | ||
workbook.FileSharing = null; | ||
|
||
#endregion FileSharing | ||
|
||
#region WorkbookProtection | ||
|
||
if (xlWorkbook.Protection.IsProtected) | ||
{ | ||
if (workbook.WorkbookProtection == null) | ||
workbook.WorkbookProtection = new WorkbookProtection(); | ||
|
||
var workbookProtection = workbook.WorkbookProtection; | ||
|
||
var protection = xlWorkbook.Protection; | ||
|
||
workbookProtection.WorkbookPassword = null; | ||
workbookProtection.WorkbookAlgorithmName = null; | ||
workbookProtection.WorkbookHashValue = null; | ||
workbookProtection.WorkbookSpinCount = null; | ||
workbookProtection.WorkbookSaltValue = null; | ||
|
||
if (protection.Algorithm == XLProtectionAlgorithm.Algorithm.SimpleHash) | ||
{ | ||
if (!String.IsNullOrWhiteSpace(protection.PasswordHash)) | ||
workbookProtection.WorkbookPassword = protection.PasswordHash; | ||
} | ||
else | ||
{ | ||
workbookProtection.WorkbookAlgorithmName = DescribedEnumParser<XLProtectionAlgorithm.Algorithm>.ToDescription(protection.Algorithm); | ||
workbookProtection.WorkbookHashValue = protection.PasswordHash; | ||
workbookProtection.WorkbookSpinCount = protection.SpinCount; | ||
workbookProtection.WorkbookSaltValue = protection.Base64EncodedSalt; | ||
} | ||
|
||
workbookProtection.LockStructure = OpenXmlHelper.GetBooleanValue(!protection.AllowedElements.HasFlag(XLWorkbookProtectionElements.Structure), false); | ||
workbookProtection.LockWindows = OpenXmlHelper.GetBooleanValue(!protection.AllowedElements.HasFlag(XLWorkbookProtectionElements.Windows), false); | ||
} | ||
else | ||
{ | ||
workbook.WorkbookProtection = null; | ||
} | ||
|
||
#endregion WorkbookProtection | ||
|
||
if (workbook.BookViews == null) | ||
workbook.BookViews = new BookViews(); | ||
|
||
if (workbook.Sheets == null) | ||
workbook.Sheets = new Sheets(); | ||
|
||
var worksheets = xlWorkbook.WorksheetsInternal; | ||
workbook.Sheets.Elements<Sheet>().Where(s => worksheets.Deleted.Contains(s.Id)).ToList().ForEach( | ||
s => s.Remove()); | ||
|
||
foreach (var sheet in workbook.Sheets.Elements<Sheet>()) | ||
{ | ||
var sheetId = (Int32)sheet.SheetId.Value; | ||
|
||
if (xlWorkbook.WorksheetsInternal.All<XLWorksheet>(w => w.SheetId != sheetId)) continue; | ||
|
||
var wks = xlWorkbook.WorksheetsInternal.Single<XLWorksheet>(w => w.SheetId == sheetId); | ||
wks.RelId = sheet.Id; | ||
sheet.Name = wks.Name; | ||
} | ||
|
||
foreach (var xlSheet in xlWorkbook.WorksheetsInternal.OrderBy<XLWorksheet, int>(w => w.Position)) | ||
{ | ||
string rId; | ||
if (String.IsNullOrWhiteSpace(xlSheet.RelId)) | ||
{ | ||
// Sheet isn't from loaded file and hasn't been saved yet. | ||
rId = xlSheet.RelId = context.RelIdGenerator.GetNext(XLWorkbook.RelType.Workbook); | ||
} | ||
else | ||
{ | ||
// Keep same r:id from previous file | ||
rId = xlSheet.RelId; | ||
} | ||
|
||
if (workbook.Sheets.Cast<Sheet>().All(s => s.Id != rId)) | ||
{ | ||
var newSheet = new Sheet | ||
{ | ||
Name = xlSheet.Name, | ||
Id = rId, | ||
SheetId = xlSheet.SheetId | ||
}; | ||
|
||
workbook.Sheets.AppendChild(newSheet); | ||
} | ||
} | ||
|
||
var sheetElements = from sheet in workbook.Sheets.Elements<Sheet>() | ||
join worksheet in ((IEnumerable<XLWorksheet>)xlWorkbook.WorksheetsInternal) on sheet.Id.Value | ||
equals worksheet.RelId | ||
orderby worksheet.Position | ||
select sheet; | ||
|
||
UInt32 firstSheetVisible = 0; | ||
var activeTab = | ||
(from us in xlWorkbook.UnsupportedSheets where us.IsActive select (UInt32)us.Position - 1).FirstOrDefault(); | ||
var foundVisible = false; | ||
|
||
var totalSheets = sheetElements.Count() + xlWorkbook.UnsupportedSheets.Count; | ||
for (var p = 1; p <= totalSheets; p++) | ||
{ | ||
if (xlWorkbook.UnsupportedSheets.All(us => us.Position != p)) | ||
{ | ||
var sheet = sheetElements.ElementAt(p - xlWorkbook.UnsupportedSheets.Count(us => us.Position <= p) - 1); | ||
workbook.Sheets.RemoveChild(sheet); | ||
workbook.Sheets.AppendChild(sheet); | ||
var xlSheet = xlWorkbook.Worksheet(sheet.Name); | ||
if (xlSheet.Visibility != XLWorksheetVisibility.Visible) | ||
sheet.State = xlSheet.Visibility.ToOpenXml(); | ||
else | ||
sheet.State = null; | ||
|
||
if (foundVisible) continue; | ||
|
||
if (sheet.State == null || sheet.State == SheetStateValues.Visible) | ||
foundVisible = true; | ||
else | ||
firstSheetVisible++; | ||
} | ||
else | ||
{ | ||
var sheetId = xlWorkbook.UnsupportedSheets.First(us => us.Position == p).SheetId; | ||
var sheet = workbook.Sheets.Elements<Sheet>().First(s => s.SheetId == sheetId); | ||
workbook.Sheets.RemoveChild(sheet); | ||
workbook.Sheets.AppendChild(sheet); | ||
} | ||
} | ||
|
||
var workbookView = workbook.BookViews.Elements<WorkbookView>().FirstOrDefault(); | ||
|
||
if (activeTab == 0) | ||
{ | ||
UInt32? firstActiveTab = null; | ||
UInt32? firstSelectedTab = null; | ||
foreach (var ws in worksheets) | ||
{ | ||
if (ws.TabActive) | ||
{ | ||
firstActiveTab = (UInt32)(ws.Position - 1); | ||
break; | ||
} | ||
|
||
if (ws.TabSelected) | ||
{ | ||
firstSelectedTab = (UInt32)(ws.Position - 1); | ||
} | ||
} | ||
|
||
activeTab = firstActiveTab | ||
?? firstSelectedTab | ||
?? firstSheetVisible; | ||
} | ||
|
||
if (workbookView == null) | ||
{ | ||
workbookView = new WorkbookView { ActiveTab = activeTab, FirstSheet = firstSheetVisible }; | ||
workbook.BookViews.AppendChild(workbookView); | ||
} | ||
else | ||
{ | ||
workbookView.ActiveTab = activeTab; | ||
workbookView.FirstSheet = firstSheetVisible; | ||
} | ||
|
||
var definedNames = new DefinedNames(); | ||
foreach (var worksheet in xlWorkbook.WorksheetsInternal) | ||
{ | ||
var wsSheetId = worksheet.SheetId; | ||
UInt32 sheetId = 0; | ||
foreach (var s in workbook.Sheets.Elements<Sheet>().TakeWhile(s => s.SheetId != wsSheetId)) | ||
{ | ||
sheetId++; | ||
} | ||
|
||
if (worksheet.PageSetup.PrintAreas.Any()) | ||
{ | ||
var definedName = new DefinedName { Name = "_xlnm.Print_Area", LocalSheetId = sheetId }; | ||
var worksheetName = worksheet.Name; | ||
var definedNameText = worksheet.PageSetup.PrintAreas.Aggregate(String.Empty, | ||
(current, printArea) => | ||
current + | ||
(worksheetName.EscapeSheetName() + "!" + | ||
printArea.RangeAddress. | ||
FirstAddress.ToStringFixed( | ||
XLReferenceStyle.A1) + | ||
":" + | ||
printArea.RangeAddress. | ||
LastAddress.ToStringFixed( | ||
XLReferenceStyle.A1) + | ||
",")); | ||
definedName.Text = definedNameText.Substring(0, definedNameText.Length - 1); | ||
definedNames.AppendChild(definedName); | ||
} | ||
|
||
if (worksheet.AutoFilter.IsEnabled) | ||
{ | ||
var definedName = new DefinedName | ||
{ | ||
Name = "_xlnm._FilterDatabase", | ||
LocalSheetId = sheetId, | ||
Text = worksheet.Name.EscapeSheetName() + "!" + | ||
worksheet.AutoFilter.Range.RangeAddress.FirstAddress.ToStringFixed( | ||
XLReferenceStyle.A1) + | ||
":" + | ||
worksheet.AutoFilter.Range.RangeAddress.LastAddress.ToStringFixed( | ||
XLReferenceStyle.A1), | ||
Hidden = BooleanValue.FromBoolean(true) | ||
}; | ||
definedNames.AppendChild(definedName); | ||
} | ||
|
||
foreach (var nr in worksheet.NamedRanges.Where(n => n.Name != "_xlnm._FilterDatabase")) | ||
{ | ||
var definedName = new DefinedName | ||
{ | ||
Name = nr.Name, | ||
LocalSheetId = sheetId, | ||
Text = nr.ToString() | ||
}; | ||
|
||
if (!nr.Visible) | ||
definedName.Hidden = BooleanValue.FromBoolean(true); | ||
|
||
if (!String.IsNullOrWhiteSpace(nr.Comment)) | ||
definedName.Comment = nr.Comment; | ||
definedNames.AppendChild(definedName); | ||
} | ||
|
||
var definedNameTextRow = String.Empty; | ||
var definedNameTextColumn = String.Empty; | ||
if (worksheet.PageSetup.FirstRowToRepeatAtTop > 0) | ||
{ | ||
definedNameTextRow = worksheet.Name.EscapeSheetName() + "!" + worksheet.PageSetup.FirstRowToRepeatAtTop | ||
+ ":" + worksheet.PageSetup.LastRowToRepeatAtTop; | ||
} | ||
if (worksheet.PageSetup.FirstColumnToRepeatAtLeft > 0) | ||
{ | ||
var minColumn = worksheet.PageSetup.FirstColumnToRepeatAtLeft; | ||
var maxColumn = worksheet.PageSetup.LastColumnToRepeatAtLeft; | ||
definedNameTextColumn = worksheet.Name.EscapeSheetName() + "!" + | ||
XLHelper.GetColumnLetterFromNumber(minColumn) | ||
+ ":" + XLHelper.GetColumnLetterFromNumber(maxColumn); | ||
} | ||
|
||
string titles; | ||
if (definedNameTextColumn.Length > 0) | ||
{ | ||
titles = definedNameTextColumn; | ||
if (definedNameTextRow.Length > 0) | ||
titles += "," + definedNameTextRow; | ||
} | ||
else | ||
titles = definedNameTextRow; | ||
|
||
if (titles.Length <= 0) continue; | ||
|
||
var definedName2 = new DefinedName | ||
{ | ||
Name = "_xlnm.Print_Titles", | ||
LocalSheetId = sheetId, | ||
Text = titles | ||
}; | ||
|
||
definedNames.AppendChild(definedName2); | ||
} | ||
|
||
foreach (var nr in xlWorkbook.NamedRanges.OfType<XLNamedRange>()) | ||
{ | ||
var refersTo = string.Join(",", nr.RangeList | ||
.Select(r => r.StartsWith("#REF!") ? "#REF!" : r)); | ||
|
||
var definedName = new DefinedName | ||
{ | ||
Name = nr.Name, | ||
Text = refersTo | ||
}; | ||
|
||
if (!nr.Visible) | ||
definedName.Hidden = BooleanValue.FromBoolean(true); | ||
|
||
if (!String.IsNullOrWhiteSpace(nr.Comment)) | ||
definedName.Comment = nr.Comment; | ||
definedNames.AppendChild(definedName); | ||
} | ||
|
||
workbook.DefinedNames = definedNames; | ||
|
||
if (workbook.CalculationProperties == null) | ||
workbook.CalculationProperties = new CalculationProperties { CalculationId = 125725U }; | ||
|
||
if (xlWorkbook.CalculateMode == XLCalculateMode.Default) | ||
workbook.CalculationProperties.CalculationMode = null; | ||
else | ||
workbook.CalculationProperties.CalculationMode = xlWorkbook.CalculateMode.ToOpenXml(); | ||
|
||
if (xlWorkbook.ReferenceStyle == XLReferenceStyle.Default) | ||
workbook.CalculationProperties.ReferenceMode = null; | ||
else | ||
workbook.CalculationProperties.ReferenceMode = xlWorkbook.ReferenceStyle.ToOpenXml(); | ||
|
||
if (xlWorkbook.CalculationOnSave) workbook.CalculationProperties.CalculationOnSave = xlWorkbook.CalculationOnSave; | ||
if (xlWorkbook.ForceFullCalculation) workbook.CalculationProperties.ForceFullCalculation = xlWorkbook.ForceFullCalculation; | ||
if (xlWorkbook.FullCalculationOnLoad) workbook.CalculationProperties.FullCalculationOnLoad = xlWorkbook.FullCalculationOnLoad; | ||
if (xlWorkbook.FullPrecision) workbook.CalculationProperties.FullPrecision = xlWorkbook.FullPrecision; | ||
} | ||
|
||
} | ||
} |
Oops, something went wrong.