/// <summary> /// No custom properties? Add the part, and the collection of properties /// </summary> private static CustomFilePropertiesPart InitializeCustomDocumentProperties(OpenXmlPackage document) { CustomFilePropertiesPart customProperties = null; if (document.GetType() == typeof(WordprocessingDocument)) { var word = document as WordprocessingDocument; if (word != null) { customProperties = word.AddCustomFilePropertiesPart(); } } else if (document.GetType() == typeof(SpreadsheetDocument)) { var excel = document as SpreadsheetDocument; if (excel != null) { customProperties = excel.AddCustomFilePropertiesPart(); } } else { throw new ArgumentException($"unkown type of {nameof(document)} [{document.GetType()}]"); } if (customProperties == null) { throw new Exception("customDocumentProperties could not be initialized"); } customProperties.Properties = new Properties(); return(customProperties); }
private static CustomFilePropertiesPart GetCustomDocumentProperties(OpenXmlPackage document) { CustomFilePropertiesPart customProps = null; if (document.GetType() == typeof(WordprocessingDocument)) { var word = document as WordprocessingDocument; if (word != null) { customProps = word.CustomFilePropertiesPart; } } else if (document.GetType() == typeof(SpreadsheetDocument)) { var excel = document as SpreadsheetDocument; if (excel != null) { customProps = excel.CustomFilePropertiesPart; } } if (customProps == null) { customProps = InitializeCustomDocumentProperties(document); } return(customProps); }
/// <summary> /// Checks if SDK recognizes OOXML Iso Strict file when opening /// </summary> /// <param name="package">OOXML Documents to verify</param> /// <returns></returns> private bool IsIsoStrictFile(OpenXmlPackage package) { // StrictTranslation is an internal property that indicates which file format of OOXML file is opened, Transitional (false) or Strict (true) PropertyInfo propertyInfo = package.GetType().GetProperty("StrictTranslation", BindingFlags.NonPublic | BindingFlags.GetProperty | BindingFlags.Instance); return((bool)propertyInfo.GetValue(package, null)); }
private static void ValidatePackageStructure(OpenXmlPackage document, ValidationContext context) { var documentName = document.GetType().Name; var errors = new PackageValidator(document).Validate(context.FileFormat) .Select(e => { var errorInfo = new ValidationErrorInfo { ErrorType = ValidationErrorType.Package, Id = "Pkg_" + e.MessageId, }; string name; switch (errorInfo.Id) { case "Pkg_PartIsNotAllowed": Debug.Assert(e.SubPart != null); name = e.Part != null ? GetPartNameAndUri(e.Part) : documentName; errorInfo.Description = SR.Format(ValidationResources.Pkg_PartIsNotAllowed, name, GetPartNameAndUri(e.SubPart)); break; case "Pkg_RequiredPartDoNotExist": errorInfo.Description = SR.Format(ValidationResources.Pkg_RequiredPartDoNotExist, e.PartClassName); break; case "Pkg_OnlyOnePartAllowed": name = e.Part != null ? GetPartNameAndUri(e.Part) : documentName; errorInfo.Description = SR.Format(ValidationResources.Pkg_OnlyOnePartAllowed, name, e.PartClassName); #if DEBUG Debug.Assert(e.SubPart != null); errorInfo.RelatedPart = e.SubPart; #endif break; case "Pkg_ExtendedPartIsOpenXmlPart": Debug.Assert(e.SubPart != null); errorInfo.Description = SR.Format(ValidationResources.Pkg_ExtendedPartIsOpenXmlPart, GetPartUri(e.SubPart)); break; case "Pkg_DataPartReferenceIsNotAllowed": Debug.Assert(e.DataPartReferenceRelationship != null); name = e.Part != null ? GetPartNameAndUri(e.Part) : documentName; errorInfo.Description = SR.Format(ValidationResources.Pkg_PartIsNotAllowed, name, e.DataPartReferenceRelationship.Uri); break; case "Pkg_InvalidContentTypePart": // won't get this error. default: Debug.Assert(false, "Invalid package validation event."); break; } if (e.Part != null) { errorInfo.Part = e.Part; } errorInfo.RelatedPart = e.SubPart; return(errorInfo); }); context.Errors.AddRange(errors); }
private static string GetDocumentName(OpenXmlPackage document) { return(document.GetType().Name); }
private static string GetDocumentName(OpenXmlPackage document) { return document.GetType().Name; }
private void ValidatePackageStructure(OpenXmlPackage document, ValidationContext context) { var documentName = document.GetType().Name; #pragma warning disable CS0618 // Type or member is obsolete var packageValidationSettings = new OpenXmlPackageValidationSettings(); #pragma warning restore CS0618 // Type or member is obsolete packageValidationSettings.EventHandler += OnPackageValidationError; document.Validate(packageValidationSettings, _validationSettings.FileFormat); #pragma warning disable CS0618 // Type or member is obsolete void OnPackageValidationError(Object sender, OpenXmlPackageValidationEventArgs e) #pragma warning restore CS0618 // Type or member is obsolete { var errorInfo = new ValidationErrorInfo { ErrorType = ValidationErrorType.Package, Id = "Pkg_" + e.MessageId }; string name; switch (errorInfo.Id) { case "Pkg_PartIsNotAllowed": Debug.Assert(e.SubPart != null); name = e.Part != null?GetPartNameAndUri(e.Part) : documentName; errorInfo.Description = String.Format(CultureInfo.CurrentUICulture, ValidationResources.Pkg_PartIsNotAllowed, name, GetPartNameAndUri(e.SubPart)); break; case "Pkg_RequiredPartDoNotExist": errorInfo.Description = string.Format(CultureInfo.CurrentUICulture, ValidationResources.Pkg_RequiredPartDoNotExist, e.PartClassName); break; case "Pkg_OnlyOnePartAllowed": name = e.Part != null?GetPartNameAndUri(e.Part) : documentName; errorInfo.Description = String.Format(CultureInfo.CurrentUICulture, ValidationResources.Pkg_OnlyOnePartAllowed, name, e.PartClassName); #if DEBUG Debug.Assert(e.SubPart != null); errorInfo.RelatedPart = e.SubPart; #endif break; case "Pkg_ExtendedPartIsOpenXmlPart": Debug.Assert(e.SubPart != null); errorInfo.Description = string.Format(CultureInfo.CurrentUICulture, ValidationResources.Pkg_ExtendedPartIsOpenXmlPart, GetPartUri(e.SubPart)); break; case "Pkg_DataPartReferenceIsNotAllowed": Debug.Assert(e.DataPartReferenceRelationship != null); name = e.Part != null?GetPartNameAndUri(e.Part) : documentName; errorInfo.Description = String.Format(CultureInfo.CurrentUICulture, ValidationResources.Pkg_PartIsNotAllowed, name, e.DataPartReferenceRelationship.Uri); break; case "Pkg_InvalidContentTypePart": // won't get this error. default: Debug.Assert(false, "Invalid package validation event."); break; } if (e.Part != null) { errorInfo.Part = e.Part; errorInfo.Path = new XmlPath(e.Part); } errorInfo.RelatedPart = e.SubPart; context.AddError(errorInfo); } }
/// <summary> /// Converts an <see cref="OpenXmlPackage"/> into a CodeDom object that can be used /// to build code in a given .NET language to build the referenced <paramref name="pkg"/>. /// </summary> /// <param name="pkg"> /// The <see cref="OpenXmlPackage"/> object to generate source code for. /// </param> /// <param name="settings"> /// The <see cref="ISerializeSettings"/> to use during the code generation /// process. /// </param> /// <returns> /// A new <see cref="CodeCompileUnit"/> containing the instructions to build /// the referenced <see cref="OpenXmlPackage"/>. /// </returns> public static CodeCompileUnit GenerateSourceCode(this OpenXmlPackage pkg, ISerializeSettings settings) { const string pkgVarName = "pkg"; const string paramName = "pathToFile"; var result = new CodeCompileUnit(); var pkgType = pkg.GetType(); var pkgTypeName = pkgType.Name; var partTypeCounts = new Dictionary<string, int>(); var namespaces = new SortedSet<string>(); var mainNamespace = new CodeNamespace(settings.NamespaceName); var bluePrints = new OpenXmlPartBluePrintCollection(); CodeConditionStatement conditionStatement; CodeMemberMethod entryPoint; CodeMemberMethod createParts; CodeTypeDeclaration mainClass; CodeTryCatchFinallyStatement tryAndCatch; CodeFieldReferenceExpression docTypeVarRef = null; Type docTypeEnum; string docTypeEnumVal; KeyValuePair<string, Type> rootVarType; // Add all initial namespace names first namespaces.Add("System"); // The OpenXmlDocument derived parts all contain a property called "DocumentType" // but the property types differ depending on the derived part. Need to get both // the enum name of selected value to use as a parameter for the Create statement. switch (pkg) { case PresentationDocument p: docTypeEnum = p.DocumentType.GetType(); docTypeEnumVal = p.DocumentType.ToString(); break; case SpreadsheetDocument s: docTypeEnum = s.DocumentType.GetType(); docTypeEnumVal = s.DocumentType.ToString(); break; case WordprocessingDocument w: docTypeEnum = w.DocumentType.GetType(); docTypeEnumVal = w.DocumentType.ToString(); break; default: throw new ArgumentException("object is not a recognized OpenXmlPackage type.", nameof(pkg)); } // Create the entry method entryPoint = new CodeMemberMethod() { Name = "CreatePackage", ReturnType = new CodeTypeReference(), Attributes = MemberAttributes.Public | MemberAttributes.Final }; entryPoint.Parameters.Add( new CodeParameterDeclarationExpression(typeof(string).Name, paramName)); // Create package declaration expression first entryPoint.Statements.Add(new CodeVariableDeclarationStatement(pkgTypeName, pkgVarName, new CodePrimitiveExpression(null))); // Add the required DocumentType parameter here, if available if (docTypeEnum != null) { namespaces.Add(docTypeEnum.Namespace); var simpleFieldRef = new CodeVariableReferenceExpression( docTypeEnum.GetObjectTypeName(settings.NamespaceAliasOptions.Order)); docTypeVarRef = new CodeFieldReferenceExpression(simpleFieldRef, docTypeEnumVal); } // initialize package var var pkgCreateMethod = new CodeMethodReferenceExpression( new CodeTypeReferenceExpression(pkgTypeName), "Create"); var pkgCreateInvoke = new CodeMethodInvokeExpression(pkgCreateMethod, new CodeArgumentReferenceExpression(paramName), docTypeVarRef); var initializePkg = new CodeAssignStatement( new CodeVariableReferenceExpression(pkgVarName), pkgCreateInvoke); // Call CreateParts method var partsCreateMethod = new CodeMethodReferenceExpression( new CodeThisReferenceExpression(), "CreateParts"); var partsCreateInvoke = new CodeMethodInvokeExpression( partsCreateMethod, new CodeDirectionExpression(FieldDirection.Ref, new CodeVariableReferenceExpression(pkgVarName))); // Clean up pkg var var pkgDisposeMethod = new CodeMethodReferenceExpression( new CodeVariableReferenceExpression(pkgVarName), "Dispose"); var pkgDisposeInvoke = new CodeMethodInvokeExpression( pkgDisposeMethod); // Setup the try/catch statement to properly initialize the pkg var tryAndCatch = new CodeTryCatchFinallyStatement(); // Try statements tryAndCatch.TryStatements.Add(initializePkg); tryAndCatch.TryStatements.AddBlankLine(); tryAndCatch.TryStatements.Add(partsCreateInvoke); // If statement to ensure pkgVarName is not null before trying to dispose conditionStatement = new CodeConditionStatement( new CodeBinaryOperatorExpression( new CodeVariableReferenceExpression(pkgVarName), CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null))); conditionStatement.TrueStatements.Add(pkgDisposeInvoke); // Finally statements tryAndCatch.FinallyStatements.Add(conditionStatement); entryPoint.Statements.Add(tryAndCatch); // Create the CreateParts method createParts = new CodeMemberMethod() { Name = "CreateParts", ReturnType = new CodeTypeReference(), Attributes = MemberAttributes.Private | MemberAttributes.Final }; createParts.Parameters.Add(new CodeParameterDeclarationExpression(pkgTypeName, pkgVarName) { Direction = FieldDirection.Ref }); // Add all of the child part references here if (pkg.Parts != null) { var customNewPartTypes = new Type[] { typeof(PresentationPart), typeof(WorkbookPart), typeof(MainDocumentPart) }; OpenXmlPartBluePrint bpTemp; CodeMethodReferenceExpression referenceExpression; CodeMethodInvokeExpression invokeExpression; CodeMethodReferenceExpression methodReference; Type currentPartType; string varName = null; string initMethodName = null; string mainPartTypeName; foreach (var pair in pkg.Parts) { // Need special handling rules for WorkbookPart, MainDocumentPart, and PresentationPart // objects. They cannot be created using the usual "AddNewPart" methods, unfortunately. currentPartType = pair.OpenXmlPart.GetType(); if (customNewPartTypes.Contains(currentPartType)) { namespaces.Add(currentPartType.Namespace); mainPartTypeName = currentPartType.Name; if (pair.OpenXmlPart is PresentationPart) { varName = "presentationPart"; initMethodName = "AddPresentationPart"; } else if (pair.OpenXmlPart is WorkbookPart) { varName = "workbookPart"; initMethodName = "AddWorkbookPart"; } else if (pair.OpenXmlPart is MainDocumentPart) { varName = "mainDocumentPart"; initMethodName = "AddMainDocumentPart"; } rootVarType = new KeyValuePair<string, Type>(varName, currentPartType); // Setup the blueprint bpTemp = new OpenXmlPartBluePrint(pair.OpenXmlPart, varName); // Setup the add new part statement for the current OpenXmlPart object referenceExpression = new CodeMethodReferenceExpression( new CodeArgumentReferenceExpression(pkgVarName), initMethodName); invokeExpression = new CodeMethodInvokeExpression(referenceExpression); createParts.Statements.Add(new CodeVariableDeclarationStatement(mainPartTypeName, varName, invokeExpression)); // Add the call to the method to populate the current OpenXmlPart object methodReference = new CodeMethodReferenceExpression(new CodeThisReferenceExpression(), bpTemp.MethodName); createParts.Statements.Add(new CodeMethodInvokeExpression(methodReference, new CodeDirectionExpression(FieldDirection.Ref, new CodeVariableReferenceExpression(varName)))); // Add the current main part to the collection of blueprints to ensure that the appropriate 'Generate*' // method is added to the collection of helper methods. bluePrints.Add(bpTemp); // Add a blank line for clarity createParts.Statements.AddBlankLine(); // now create the child parts for the current one an continue the loop to avoid creating // an additional invalid 'AddNewPart' method for the current main part. foreach (var child in pair.OpenXmlPart.Parts) { createParts.Statements.AddRange( OpenXmlPartExtensions.BuildEntryMethodCodeStatements( child, settings, partTypeCounts, namespaces, bluePrints, rootVarType)); } continue; } rootVarType = new KeyValuePair<string, Type>(pkgVarName, pkgType); createParts.Statements.AddRange( OpenXmlPartExtensions.BuildEntryMethodCodeStatements( pair, settings, partTypeCounts, namespaces, bluePrints, rootVarType)); } } // Setup the main class next mainClass = new CodeTypeDeclaration($"{pkgTypeName}BuilderClass") { IsClass = true, Attributes = MemberAttributes.Public }; // Setup the main class members mainClass.Members.Add(entryPoint); mainClass.Members.Add(createParts); mainClass.Members.AddRange(OpenXmlPartExtensions.BuildHelperMethods (bluePrints, settings, namespaces)); // Setup the imports var codeNameSpaces = new List<CodeNamespaceImport>(namespaces.Count); foreach (var ns in namespaces) { codeNameSpaces.Add(ns.GetCodeNamespaceImport(settings.NamespaceAliasOptions)); } codeNameSpaces.Sort(new CodeNamespaceImportComparer()); mainNamespace.Imports.AddRange(codeNameSpaces.ToArray()); mainNamespace.Types.Add(mainClass); // Finish up result.Namespaces.Add(mainNamespace); return result; }