Exemplo n.º 1
0
        private static void createMsWordDocOrPdfFromMsWordDoc(
            MergeRowTree rowTree, bool ensureAllFieldsHaveValues, Stream inputStream, Stream destinationStream, bool saveAsMsWordDoc)
        {
            var doc = new Aspose.Words.Document(inputStream);

            // This is a hack we need to do because Aspose changed MailMerge.Execute to only support a single level of data. Since we support multiple levels, i.e.
            // child data, we need to use MailMerge.ExecuteWithRegions, which associates the specified enumerator with the top level "table" in the document instead
            // of the document itself. See http://www.aspose.com/community/forums/thread/315734.aspx.
            var builder = new Aspose.Words.DocumentBuilder(doc);

            builder.MoveToDocumentStart();
            builder.InsertField("MERGEFIELD TableStart:Main");
            builder.MoveToDocumentEnd();
            builder.InsertField("MERGEFIELD TableEnd:Main");

            doc.MailMerge.CleanupOptions       = MailMergeCleanupOptions.RemoveUnusedRegions;
            doc.MailMerge.FieldMergingCallback = new ImageFieldMergingCallBack();
            try {
                doc.MailMerge.ExecuteWithRegions(new AsposeMergeRowEnumerator("Main", rowTree.Rows, ensureAllFieldsHaveValues));
            }
            catch (InvalidOperationException e) {
                // Aspose throws InvalidOperationException when there are problems with the template, such as a badly-formed region.
                throw new MailMergingException(e.Message);
            }
            doc.Save(destinationStream, saveAsMsWordDoc ? Aspose.Words.SaveFormat.Docx : Aspose.Words.SaveFormat.Pdf);
        }
Exemplo n.º 2
0
 /// <summary>
 /// Creates a display from this row tree. The display is an ordered list of rows, in which each row is a form-item list of values and a section for each
 /// child row-tree display.
 /// </summary>
 /// <param name="rowTree">The merge row tree.</param>
 /// <param name="fieldNameTree">The fields that you want to include in the display. Pass null for all.</param>
 /// <param name="omitListIfSingleRow">Pass true to omit the root ordered-list component if the tree has exactly one row.</param>
 /// <param name="useSubtractiveMode">Pass true if you want the field-name tree to represent excluded fields, rather than included fields.</param>
 public static FlowComponent ToRowTreeDisplay(
     this MergeRowTree rowTree, MergeFieldNameTree fieldNameTree, bool omitListIfSingleRow = false, bool useSubtractiveMode = false) =>
 new GenericFlowContainer(
     omitListIfSingleRow && rowTree.Rows.Count() == 1
                                 ? getRow(rowTree.Rows.Single(), fieldNameTree, useSubtractiveMode)
                                 : new StackList(from i in rowTree.Rows select getRow(i, fieldNameTree, useSubtractiveMode).ToComponentListItem()).ToCollection(),
     classes: rowTreeClass);
Exemplo n.º 3
0
        /// <summary>
        /// Merges a row tree with a PDF document containing form fields.
        /// </summary>
        public static void CreatePdf(
            MergeRowTree rowTree, bool ensureAllFieldsHaveValues, MemoryStream sourcePdfStream, Stream destinationStream,
            bool useLegacyBehaviorOfIgnoringInvalidFields = false)
        {
            var streams = new List <Stream>();

            try {
                foreach (var row in rowTree.Rows)
                {
                    var stream = new MemoryStream();
                    streams.Add(stream);

                    using (var sourcePdfMemoryStreamCopy = new MemoryStream()) {
                        // Aspose has decided that in the new Facades PDF library, they will close your source stream for you when you call doc.Save.
                        sourcePdfStream.Reset();
                        IoMethods.CopyStream(sourcePdfStream, sourcePdfMemoryStreamCopy);

                        var doc = new Aspose.Pdf.Facades.Form(sourcePdfMemoryStreamCopy);
                        foreach (var mergeField in doc.FieldNames.Where(mergeField => !mergeField.StartsWith("noMerge")))
                        {
                            var mergeValue = row.Values.SingleOrDefault(v => v.Name == mergeField);
                            if (mergeValue == null)
                            {
                                if (useLegacyBehaviorOfIgnoringInvalidFields)
                                {
                                    continue;
                                }
                                throw new MailMergingException(string.Format("PDF document contains a merge field ({0}) that does not exist.", mergeField));
                            }

                            var    mergeValueAsString = mergeValue as MergeValue <string>;
                            string value = null;
                            if (mergeValueAsString != null)
                            {
                                value = mergeValueAsString.Evaluate(ensureAllFieldsHaveValues);
                            }
                            if (value == null)
                            {
                                throw new MailMergingException("Merge field " + mergeValue.Name + " evaluates to an unsupported type.");
                            }

                            doc.FillField(mergeValue.Name, value);
                        }
                        doc.Save(stream);
                    }
                }

                if (streams.Any())
                {
                    PdfOps.ConcatPdfs(streams, destinationStream);
                }
            }
            finally {
                foreach (var i in streams)
                {
                    i.Dispose();
                }
            }
        }
Exemplo n.º 4
0
 /// <summary>
 /// Creates a response by merging a row tree with a Microsoft Word document. If you would like each row to be on a separate page, set the first paragraph in
 /// the input file to have a page break before it.
 /// </summary>
 public EwfResponse(Func <string> extensionlessFileNameCreator, MergeRowTree rowTree, bool ensureAllFieldsHaveValues, string inputFilePath)
     : this(extensionlessFileNameCreator,
            rowTree,
            ensureAllFieldsHaveValues,
            writer => {
     using (var sourceDocStream = new MemoryStream(File.ReadAllBytes(inputFilePath)))
         writer(sourceDocStream);
 }) {}
Exemplo n.º 5
0
        /// <summary>
        /// Gets a merge field name tree of the fields that are supported by the CreateXmlDocument method.
        /// </summary>
        public static MergeFieldNameTree GetXmlSupportedMergeFields(MergeRowTree rowTree)
        {
            var firstRow = rowTree.Rows.First();

            return(new MergeFieldNameTree(
                       firstRow.Values.Where(mergeValueTypeIsSupportedInXml).Select(i => i.Name),
                       childNamesAndChildren: firstRow.Children.Select(i => Tuple.Create(i.NodeName, GetXmlSupportedMergeFields(i)))));
        }
 /// <summary>
 /// Creates a response containing a tab-separated values file created from the top level of a row tree. There will be one column for each merge field
 /// specified in the list of field names.
 /// </summary>
 public static EwfResponse CreateMergedTabSeparatedValuesResponse(
     Func <string> extensionlessFileNameCreator, MergeRowTree rowTree, IEnumerable <string> fieldNames, bool omitHeaderRow = false)
 {
     return(Create(
                ContentTypes.TabSeparatedValues,
                new EwfResponseBodyCreator(writer => MergeOps.CreateTabularTextFile(rowTree, fieldNames, writer, useTabAsSeparator: true, omitHeaderRow: omitHeaderRow)),
                fileNameCreator: () => extensionlessFileNameCreator() + FileExtensions.Txt));
 }
Exemplo n.º 7
0
 /// <summary>
 /// Creates an XML document from a row tree and writes it to a stream using UTF-8 encoding.
 /// </summary>
 // If we need to start generating XML on the fly for HTTP responses, it may make sense to create an overload of this method that takes an HttpResponse
 // object instead of a stream. This new overload would use the HttpResponse.Output property to obtain a TextWriter and then create the XmlWriter on top of
 // that instead of a stream. The advantage of this approach is that the encoding of the XML would then be determined by ASP.NET, which takes into account
 // any request headers the client may have sent that pertain to the desired encoding of the response.
 public static void CreateXmlDocument(MergeRowTree rowTree, MergeFieldNameTree fieldNameTree, Stream destinationStream)
 {
     using (var writer = XmlWriter.Create(destinationStream)) {
         writer.WriteStartDocument();
         writeRowTreeXmlElement(rowTree, fieldNameTree, writer);
         writer.WriteEndDocument();
     }
 }
 /// <summary>
 /// Creates a response containing a comma-separated values (CSV) file created from the top level of a row tree. There will be one column for each merge
 /// field specified in the list of field names.
 /// </summary>
 public static EwfResponse CreateMergedCsvResponse(
     Func <string> extensionlessFileNameCreator, MergeRowTree rowTree, IEnumerable <string> fieldNames, bool omitHeaderRow = false)
 {
     return(Create(
                TewlContrib.ContentTypes.Csv,
                new EwfResponseBodyCreator(writer => MergeOps.CreateTabularTextFile(rowTree, fieldNames, writer, omitHeaderRow: omitHeaderRow)),
                fileNameCreator: () => extensionlessFileNameCreator() + FileExtensions.Csv));
 }
Exemplo n.º 9
0
 /// <summary>
 /// Merges a row tree with a PDF document containing form fields.
 /// </summary>
 public static void CreatePdf(
     MergeRowTree rowTree, bool ensureAllFieldsHaveValues, string sourcePdfFilePath, Stream destinationStream,
     bool useLegacyBehaviorOfIgnoringInvalidFields = false)
 {
     // Use a memory stream because the stream may be read multiple times and we only want to access the file once.
     using (var sourcePdfStream = new MemoryStream(File.ReadAllBytes(sourcePdfFilePath)))
         CreatePdf(rowTree, ensureAllFieldsHaveValues, sourcePdfStream, destinationStream, useLegacyBehaviorOfIgnoringInvalidFields);
 }
Exemplo n.º 10
0
 /// <summary>
 /// Creates a response by merging a row tree with a Microsoft Word document. If you would like each row to be on a separate page, set the first paragraph in
 /// the input file to have a page break before it.
 /// </summary>
 public static EwfResponse CreateMergedMsWordDocResponse(
     Func <string> extensionlessFileNameCreator, MergeRowTree rowTree, bool ensureAllFieldsHaveValues, Action <Action <Stream> > inputStreamProvider)
 {
     return(Create(
                ContentTypes.WordDoc,
                new EwfResponseBodyCreator(
                    destinationStream => inputStreamProvider(inputStream => MergeOps.CreateMsWordDoc(rowTree, ensureAllFieldsHaveValues, inputStream, destinationStream))),
                fileNameCreator: () => extensionlessFileNameCreator() + FileExtensions.WordDoc));
 }
Exemplo n.º 11
0
        /// <summary>
        /// Creates a comma-separated values (CSV) or tab-separated values file from the top level of a row tree. There will be one column for each merge field
        /// specified in the list of field names.
        /// </summary>
        public static void CreateTabularTextFile(
            MergeRowTree rowTree, IEnumerable <string> fieldNames, TextWriter destinationWriter, bool useTabAsSeparator = false, bool omitHeaderRow = false)
        {
            if (!rowTree.Rows.Any())
            {
                return;
            }

            foreach (var fieldName in fieldNames)
            {
                if (rowTree.Rows.First().Values.All(i => i.Name != fieldName))
                {
                    // Use ApplicationException instead of MailMergingException because the field names can easily be validated before this method is called.
                    throw new ApplicationException("Merge field " + fieldName + " is invalid.");
                }
            }

            var writer = useTabAsSeparator ? (TextBasedTabularDataFileWriter) new TabDelimitedFileWriter() : new CsvFileWriter();

            if (!omitHeaderRow)
            {
                writer.AddValuesToLine(
                    fieldNames.Select(fieldName => rowTree.Rows.First().Values.Single(i => i.Name == fieldName))
                    .Select(mergeValue => (object)mergeValue.Name)
                    .ToArray());
                writer.WriteCurrentLineToFile(destinationWriter);
            }

            foreach (var row in rowTree.Rows)
            {
                writer.AddValuesToLine(
                    fieldNames.Select(fieldName => row.Values.Single(i => i.Name == fieldName))
                    .Select(
                        mergeValue => {
                    var mergeValueAsString = mergeValue as MergeValue <string>;
                    if (mergeValueAsString != null)
                    {
                        return(mergeValueAsString.Evaluate(false));
                    }

                    // Use ApplicationException instead of MailMergingException because the field names can easily be validated before this method is called.
                    throw new ApplicationException("Merge field " + mergeValue.Name + " evaluates to an unsupported type.");
                })
                    .Cast <object>()
                    .ToArray());

                writer.WriteCurrentLineToFile(destinationWriter);
            }
        }
Exemplo n.º 12
0
        internal static ExcelFileWriter CreateExcelFileWriter(MergeRowTree rowTree, IEnumerable <string> fieldNames, bool useMsWordFieldNames)
        {
            var excelFile = new ExcelFileWriter();

            if (rowTree.Rows.Any())
            {
                foreach (var fieldName in fieldNames)
                {
                    if (rowTree.Rows.First().Values.All(i => i.Name != fieldName))
                    {
                        // Use ApplicationException instead of MailMergingException because the field names can easily be validated before this method is called.
                        throw new ApplicationException("Merge field " + fieldName + " is invalid.");
                    }
                }

                var sheet = excelFile.DefaultWorksheet;
                sheet.AddHeaderToWorksheet(
                    fieldNames.Select(fieldName => rowTree.Rows.First().Values.Single(i => i.Name == fieldName))
                    .Select(mergeValue => useMsWordFieldNames ? mergeValue.MsWordName : mergeValue.Name.CamelToEnglish())
                    .ToArray());
                sheet.FreezeHeaderRow();
                foreach (var row in rowTree.Rows)
                {
                    sheet.AddRowToWorksheet(
                        fieldNames.Select(fieldName => row.Values.Single(i => i.Name == fieldName))
                        .Select(
                            mergeValue => {
                        var mergeValueAsString = mergeValue as MergeValue <string>;
                        string value           = null;
                        if (mergeValueAsString != null)
                        {
                            value = mergeValueAsString.Evaluate(false);
                        }
                        if (value == null)
                        {
                            // Use ApplicationException instead of MailMergingException because the field names can easily be validated before this method is called.
                            throw new ApplicationException("Merge field " + mergeValue.Name + " evaluates to an unsupported type.");
                        }

                        return(value);
                    })
                        .ToArray());
                }
            }
            return(excelFile);
        }
Exemplo n.º 13
0
        private static void writeRowTreeXmlElement(MergeRowTree rowTree, MergeFieldNameTree fieldNameTree, XmlWriter writer)
        {
            writer.WriteStartElement(rowTree.NodeName);
            foreach (var row in rowTree.Rows)
            {
                writer.WriteStartElement(rowTree.XmlRowElementName);
                foreach (var fieldName in fieldNameTree.FieldNames)
                {
                    var mergeValue = row.Values.SingleOrDefault(i => i.Name == fieldName);
                    if (mergeValue == null)
                    {
                        // Use ApplicationException instead of MailMergingException because the field names can easily be validated before this method is called.
                        throw new ApplicationException("Merge field " + fieldName + " is invalid.");
                    }

                    writer.WriteStartElement(mergeValue.Name);
                    if (mergeValue is MergeValue <string> )
                    {
                        writer.WriteValue((mergeValue as MergeValue <string>).Evaluate(false));
                    }
                    else
                    {
                        // Use ApplicationException instead of MailMergingException because the field names can easily be validated before this method is called.
                        throw new ApplicationException("Merge field " + mergeValue.Name + " evaluates to an unsupported type.");
                    }
                    writer.WriteEndElement();
                }

                foreach (var childNameAndFieldNameTree in fieldNameTree.ChildNamesAndChildren)
                {
                    var childRowTree = row.Children.SingleOrDefault(i => i.NodeName == childNameAndFieldNameTree.Item1);
                    if (childRowTree == null)
                    {
                        // Use ApplicationException instead of MailMergingException because the child names can easily be validated before this method is called.
                        throw new ApplicationException("Child " + childNameAndFieldNameTree.Item1 + " is invalid.");
                    }
                    writeRowTreeXmlElement(childRowTree, childNameAndFieldNameTree.Item2, writer);
                }

                writer.WriteEndElement();
            }
            writer.WriteEndElement();
        }
Exemplo n.º 14
0
 /// <summary>
 /// Gets an IEnumerable of the merge field names from the top level of the specified row tree that are supported by the CreateExcelWorkbook method.
 /// </summary>
 public static IEnumerable <string> GetExcelSupportedMergeFields(MergeRowTree rowTree)
 {
     return(rowTree.Rows.First().Values.Where(mergeValueTypeIsSupportedByExcel).Select(v => v.Name));
 }
Exemplo n.º 15
0
        /// <summary>
        /// Creates a single-sheet Excel Workbook from the top level of a row tree and writes it to a stream. There will be one column for each merge field
        /// specified in the list of field names. Each column head will be named by calling ToEnglishFromCamel on the merge field's name or using the Microsoft Word
        /// name without modification, the latter if useMsWordFieldNames is true.
        /// </summary>
        public static void CreateExcelWorkbook(MergeRowTree rowTree, IEnumerable <string> fieldNames, Stream destinationStream, bool useMsWordFieldNames = false)
        {
            var excelFile = CreateExcelFileWriter(rowTree, fieldNames, useMsWordFieldNames);

            excelFile.SaveToStream(destinationStream);
        }
Exemplo n.º 16
0
 public static EwfResponse CreateExcelWorkbook(
     MergeRowTree rowTree, IEnumerable <string> fieldNames, string fileNameWithoutExtension, bool useMsWordFieldNames = false)
 {
     return(new EwfResponse(() => fileNameWithoutExtension, rowTree, fieldNames, useMsWordFieldNames: useMsWordFieldNames));
 }
Exemplo n.º 17
0
 /// <summary>
 /// Creates a response containing a single-sheet Excel workbook created from the top level of a row tree. There will be one column for each merge field
 /// specified in the list of field names. Each column head will be named by calling ToEnglishFromCamel on the merge field's name or using the Microsoft Word
 /// name without modification, the latter if useMsWordFieldNames is true.
 /// </summary>
 public EwfResponse(Func <string> extensionlessFileNameCreator, MergeRowTree rowTree, IEnumerable <string> fieldNames, bool useMsWordFieldNames = false)
     : this(extensionlessFileNameCreator, () => MergeOps.CreateExcelFileWriter(rowTree, fieldNames, useMsWordFieldNames))
 {
 }
Exemplo n.º 18
0
 /// <summary>
 /// Merges a row tree with a Microsoft Word document and writes the result to a stream as a PDF document. If you would like each row to be on a separate
 /// page, set the first paragraph in the input file to have a page break before it.
 /// </summary>
 public static void CreatePdfFromMsWordDoc(MergeRowTree rowTree, bool ensureAllFieldsHaveValues, string inputFilePath, Stream destinationStream)
 {
     using (var sourcePdfStream = new MemoryStream(File.ReadAllBytes(inputFilePath)))
         createMsWordDocOrPdfFromMsWordDoc(rowTree, ensureAllFieldsHaveValues, sourcePdfStream, destinationStream, false);
 }
Exemplo n.º 19
0
 /// <summary>
 /// Creates a merge-field-tree display from this empty row tree.
 /// </summary>
 /// <param name="emptyRowTree">The empty merge row tree.</param>
 /// <param name="name">The plural name of the data type at the top level in the row tree, e.g. Clients.</param>
 public static IReadOnlyCollection <FlowComponent> ToFieldTreeDisplay(this MergeRowTree emptyRowTree, string name) =>
 new GenericFlowContainer(getFieldTree(name, emptyRowTree.Rows), classes: fieldTreeClass).ToCollection();
Exemplo n.º 20
0
 public static EwfResponse CreateMsWordDoc(MergeRowTree rowTree, bool ensureAllFieldsHaveValues, string inputFilePath)
 {
     return(new EwfResponse(() => "MergedLetter", rowTree, ensureAllFieldsHaveValues, inputFilePath));
 }
Exemplo n.º 21
0
 /// <summary>
 /// Sets the name and the merge row tree that will be used to draw the field tree. The name should be the plural name of the data type at the top level in
 /// the row tree, e.g. Clients.
 /// </summary>
 public void SetNameAndEmptyRowTree(string name, MergeRowTree emptyRowTree)
 {
     this.name         = name;
     this.emptyRowTree = emptyRowTree;
 }
Exemplo n.º 22
0
 /// <summary>
 /// Creates a merge field tree and sets the name and empty row tree.
 /// </summary>
 public MergeFieldTree(string name, MergeRowTree emptyRowTree)
 {
     SetNameAndEmptyRowTree(name, emptyRowTree);
 }
Exemplo n.º 23
0
 public static EwfResponse CreateMsWordDoc(MergeRowTree rowTree, bool ensureAllFieldsHaveValues, Action <Action <Stream> > inputStreamProvider)
 {
     return(new EwfResponse(() => "MergedLetter", rowTree, ensureAllFieldsHaveValues, inputStreamProvider));
 }
Exemplo n.º 24
0
 /// <summary>
 /// Creates a merge field tree.
 /// </summary>
 /// <param name="name">The plural name of the data type at the top level in the row tree, e.g. Clients.</param>
 /// <param name="emptyRowTree">The merge row tree that will be used to draw the field tree.</param>
 public MergeFieldTree(string name, MergeRowTree emptyRowTree)
 {
     CssClass = CssClass.ConcatenateWithSpace("ewfMergeFieldTree");
     Controls.Add(buildTree(name, emptyRowTree.Rows));
 }
Exemplo n.º 25
0
 /// <summary>
 /// Creates a response containing a single-sheet Excel workbook created from the top level of a row tree. There will be one column for each merge field
 /// specified in the list of field names. Each column head will be named by calling ToEnglishFromCamel on the merge field's name or using the Microsoft Word
 /// name without modification, the latter if useMsWordFieldNames is true.
 /// </summary>
 public static EwfResponse CreateMergedExcelWorkbookResponse(
     Func <string> extensionlessFileNameCreator, MergeRowTree rowTree, IEnumerable <string> fieldNames, bool useMsWordFieldNames = false)
 {
     return(CreateExcelWorkbookResponse(extensionlessFileNameCreator, () => MergeOps.CreateExcelFileWriter(rowTree, fieldNames, useMsWordFieldNames)));
 }
Exemplo n.º 26
0
 /// <summary>
 /// Merges a row tree with a Microsoft Word document. If you would like each row to be on a separate page, set the first paragraph in the input file to have
 /// a page break before it.
 /// </summary>
 public static void CreateMsWordDoc(MergeRowTree rowTree, bool ensureAllFieldsHaveValues, Stream inputStream, Stream destinationStream)
 {
     createMsWordDocOrPdfFromMsWordDoc(rowTree, ensureAllFieldsHaveValues, inputStream, destinationStream, true);
 }