예제 #1
0
        /// <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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        /// <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));
        }
예제 #4
0
        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);
        }
예제 #5
0
 private static string GetDocumentName(OpenXmlPackage document)
 {
     return(document.GetType().Name);
 }
예제 #6
0
 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;
        }