Beispiel #1
0
            /// <summary>
            /// Returns true if the node passed is set as hidden, returns false if it is visible.
            /// </summary>
            private bool isHidden(Aspose.Words.Node node)
            {
                if (node is Aspose.Words.Inline)
                {
                    // If the node is Inline then cast it to retrieve the Font property which contains the hidden property
                    Aspose.Words.Inline currentNode = (Aspose.Words.Inline)node;
                    return(currentNode.Font.Hidden);
                }
                else if (node.NodeType == NodeType.Paragraph)
                {
                    // If the node is a paragraph cast it to retrieve the ParagraphBreakFont which contains the hidden property
                    Paragraph para = (Paragraph)node;
                    return(para.ParagraphBreakFont.Hidden);
                }
                else if (node is ShapeBase)
                {
                    // Node is a shape or groupshape.
                    ShapeBase shape = (ShapeBase)node;
                    return(shape.Font.Hidden);
                }
                else if (node is InlineStory)
                {
                    // Node is a comment or footnote.
                    InlineStory inlineStory = (InlineStory)node;
                    return(inlineStory.Font.Hidden);
                }

                // A node that is passed to this method which does not contain a hidden property will end up here.
                // By default nodes are not hidden so return false.
                return(false);
            }
Beispiel #2
0
        public void RemoveNodes()
        {
            Aspose.Words.Document doc = new Aspose.Words.Document();

            //ExStart
            //ExFor:Node
            //ExFor:Node.NodeType
            //ExFor:Node.Remove
            //ExSummary:Shows how to remove all nodes of a specific type from a composite node. In this example we remove tables from a section body.
            // Get the section that we want to work on.
            Aspose.Words.Section section = doc.Sections[0];
            Body body = section.Body;

            // Select the first child node in the body.
            Aspose.Words.Node curNode = body.FirstChild;

            while (curNode != null)
            {
                // Save the pointer to the next sibling node because if the current
                // node is removed from the parent in the next step, we will have
                // no way of finding the next node to continue the loop.
                Aspose.Words.Node nextNode = curNode.NextSibling;

                // A section body can contain Paragraph and Table nodes.
                // If the node is a Table, remove it from the parent.
                if (curNode.NodeType.Equals(NodeType.Table))
                {
                    curNode.Remove();
                }

                // Continue going through child nodes until null (no more siblings) is reached.
                curNode = nextNode;
            }
            //ExEnd
        }
Beispiel #3
0
        public void IndexChildNodes()
        {
            Aspose.Words.Document doc       = new Aspose.Words.Document();
            Paragraph             paragraph = (Paragraph)doc.GetChild(NodeType.Paragraph, 0, true);

            //ExStart
            //ExFor:NodeCollection.Count
            //ExFor:NodeCollection.Item
            //ExId:ChildNodesIndexer
            //ExSummary:Shows how to enumerate immediate children of a CompositeNode using indexed access.
            NodeCollection children = paragraph.ChildNodes;

            for (int i = 0; i < children.Count; i++)
            {
                Aspose.Words.Node child = children[i];

                // Paragraph may contain children of various types such as runs, shapes and so on.
                if (child.NodeType.Equals(NodeType.Run))
                {
                    // Say we found the node that we want, do something useful.
                    Run run = (Run)child;
                    Console.WriteLine(run.Text);
                }
            }
            //ExEnd
        }
Beispiel #4
0
        public void DeleteAllImagesPreOrder()
        {
            Aspose.Words.Document doc = new Aspose.Words.Document(MyDir + "Image.SampleImages.doc");
            Assert.AreEqual(6, doc.GetChildNodes(NodeType.Shape, true).Count);

            //ExStart
            //ExFor:Node.NextPreOrder
            //ExSummary:Shows how to delete all images from a document using pre-order tree traversal.
            Aspose.Words.Node curNode = doc;
            while (curNode != null)
            {
                Aspose.Words.Node nextNode = curNode.NextPreOrder(doc);

                if (curNode.NodeType.Equals(NodeType.Shape))
                {
                    Shape shape = (Shape)curNode;

                    // Several shape types can have an image including image shapes and OLE objects.
                    if (shape.HasImage)
                    {
                        shape.Remove();
                    }
                }

                curNode = nextNode;
            }
            //ExEnd

            Assert.AreEqual(1, doc.GetChildNodes(NodeType.Shape, true).Count);
            doc.Save(MyDir + "Image.DeleteAllImagesPreOrder Out.doc");
        }
 /// <summary>
 /// Goes through siblings starting from the start node until it finds a node of the specified type or null.
 /// </summary>
 private static Aspose.Words.Node FindNextSibling(Aspose.Words.Node startNode, NodeType nodeType)
 {
     for (Aspose.Words.Node node = startNode; node != null; node = node.NextSibling)
     {
         if (node.NodeType.Equals(nodeType))
         {
             return(node);
         }
     }
     return(null);
 }
Beispiel #6
0
        public static void GetParentNode()
        {
            //ExStart:GetParentNode
            // Create a new empty document. It has one section.
            Document doc = new Document();

            // The section is the first child node of the document.
            Aspose.Words.Node section = doc.FirstChild;
            // The section's parent node is the document.
            Console.WriteLine("Section parent is the document: " + (doc == section.ParentNode));
            //ExEnd:GetParentNode
        }
        /// <summary>
        /// Removes nodes from start up to but not including the end node.
        /// Start and end are assumed to have the same parent.
        /// </summary>
        private static void RemoveSameParent(Aspose.Words.Node startNode, Aspose.Words.Node endNode)
        {
            if ((endNode != null) && (startNode.ParentNode != endNode.ParentNode))
            {
                throw new ArgumentException("Start and end nodes are expected to have the same parent.");
            }

            Aspose.Words.Node curChild = startNode;
            while ((curChild != null) && (curChild != endNode))
            {
                Aspose.Words.Node nextChild = curChild.NextSibling;
                curChild.Remove();
                curChild = nextChild;
            }
        }
Beispiel #8
0
        /// <summary>
        /// A simple function that will walk through all children of a specified node recursively
        /// and print the type of each node to the screen.
        /// </summary>
        public static void TraverseAllNodes(CompositeNode parentNode)
        {
            // This is the most efficient way to loop through immediate children of a node.
            for (Aspose.Words.Node childNode = parentNode.FirstChild; childNode != null; childNode = childNode.NextSibling)
            {
                // Do some useful work.
                Console.WriteLine(Aspose.Words.Node.NodeTypeToString(childNode.NodeType));

                // Recurse into the node if it is a composite node.
                if (childNode.IsComposite)
                {
                    TraverseAllNodes((CompositeNode)childNode);
                }
            }
        }
        /// <summary>
        /// Retrieves text from start up to but not including the end node.
        /// </summary>
        private static string GetTextSameParent(Aspose.Words.Node startNode, Aspose.Words.Node endNode)
        {
            if ((endNode != null) && (startNode.ParentNode != endNode.ParentNode))
            {
                throw new ArgumentException("Start and end nodes are expected to have the same parent.");
            }

            StringBuilder builder = new StringBuilder();

            for (Aspose.Words.Node child = startNode; !child.Equals(endNode); child = child.NextSibling)
            {
                builder.Append(child.GetText());
            }

            return(builder.ToString());
        }
Beispiel #10
0
        public void GetNodeTypeEnums()
        {
            //ExStart
            //ExFor:Paragraph.NodeType
            //ExFor:Table.NodeType
            //ExFor:Node.NodeType
            //ExFor:Footnote.NodeType
            //ExFor:FormField.NodeType
            //ExFor:SmartTag.NodeType
            //ExFor:Cell.NodeType
            //ExFor:Row.NodeType
            //ExFor:Document.NodeType
            //ExFor:Comment.NodeType
            //ExFor:Run.NodeType
            //ExFor:Section.NodeType
            //ExFor:SpecialChar.NodeType
            //ExFor:Shape.NodeType
            //ExFor:FieldEnd.NodeType
            //ExFor:FieldSeparator.NodeType
            //ExFor:FieldStart.NodeType
            //ExFor:BookmarkStart.NodeType
            //ExFor:CommentRangeEnd.NodeType
            //ExFor:BuildingBlock.NodeType
            //ExFor:GlossaryDocument.NodeType
            //ExFor:BookmarkEnd.NodeType
            //ExFor:GroupShape.NodeType
            //ExFor:CommentRangeStart.NodeType
            //ExId:GetNodeTypeEnums
            //ExSummary:Shows how to retrieve the NodeType enumeration of nodes.
            Aspose.Words.Document doc = new Aspose.Words.Document(MyDir + "Document.doc");

            // Let's pick a node that we can't be quite sure of what type it is.
            // In this case lets pick the first node of the first paragraph in the body of the document
            Aspose.Words.Node node = doc.FirstSection.Body.FirstParagraph.FirstChild;
            Console.WriteLine("NodeType of first child: " + Aspose.Words.Node.NodeTypeToString(node.NodeType));

            // This time let's pick a node that we know the type of. Create a new paragraph and a table node.
            Paragraph para  = new Paragraph(doc);
            Table     table = new Table(doc);

            // Access to NodeType for typed nodes will always return their specific NodeType.
            // i.e A paragraph node will always return NodeType.Paragraph, a table node will always return NodeType.Table.
            Console.WriteLine("NodeType of Paragraph: " + Aspose.Words.Node.NodeTypeToString(para.NodeType));
            Console.WriteLine("NodeType of Table: " + Aspose.Words.Node.NodeTypeToString(table.NodeType));
            //ExEnd
        }
Beispiel #11
0
        public void GetParentNode()
        {
            //ExStart
            //ExFor:Node.ParentNode
            //ExId:AccessParentNode
            //ExSummary:Shows how to access the parent node.
            // Create a new empty document. It has one section.
            Aspose.Words.Document doc = new Aspose.Words.Document();

            // The section is the first child node of the document.
            Aspose.Words.Node section = doc.FirstChild;

            // The section's parent node is the document.
            Console.WriteLine("Section parent is the document: " + (doc == section.ParentNode));
            //ExEnd

            Assert.AreEqual(doc, section.ParentNode);
        }
Beispiel #12
0
        public void CompositeNode_SelectNodes()
        {
            //ExStart
            //ExFor:CompositeNode.SelectSingleNode
            //ExFor:CompositeNode.SelectNodes
            //ExSummary:Shows how to select certain nodes by using an XPath expression.
            Aspose.Words.Document doc = new Aspose.Words.Document(MyDir + "Table.Document.doc");

            // This expression will extract all paragraph nodes which are descendants of any table node in the document.
            // This will return any paragraphs which are in a table.
            NodeList nodeList = doc.SelectNodes("//Table//Paragraph");

            // This expression will select any paragraphs that are direct children of any body node in the document.
            nodeList = doc.SelectNodes("//Body/Paragraph");

            // Use SelectSingleNode to select the first result of the same expression as above.
            Aspose.Words.Node node = doc.SelectSingleNode("//Body/Paragraph");
            //ExEnd
        }
Beispiel #13
0
        /// <summary>
        /// Calculates what level a table is nested inside other tables.
        /// <returns>
        /// An integer containing the level the table is nested at.
        /// 0 = Table is not nested inside any other table
        /// 1 = Table is nested within one parent table
        /// 2 = Table is nested within two parent tables etc..</returns>
        /// </summary>
        private static int GetNestedDepthOfTable(Table table)
        {
            int depth = 0;

            NodeType type = table.NodeType;

            // The parent of the table will be a Cell, instead attempt to find a grandparent that is of type Table
            Aspose.Words.Node parent = table.GetAncestor(type);

            while (parent != null)
            {
                // Every time we find a table a level up we increase the depth counter and then try to find an
                // ancestor of type table from the parent.
                depth++;
                parent = parent.GetAncestor(type);
            }

            return(depth);
        }
Beispiel #14
0
        public static void IndexChildNodes()
        {
            //ExStart:IndexChildNodes
            Document       doc       = new Document();
            Paragraph      paragraph = (Paragraph)doc.GetChild(NodeType.Paragraph, 0, true);
            NodeCollection children  = paragraph.ChildNodes;

            for (int i = 0; i < children.Count; i++)
            {
                Aspose.Words.Node child = children[i];

                // Paragraph may contain children of various types such as runs, shapes and so on.
                if (child.NodeType.Equals(NodeType.Run))
                {
                    // Say we found the node that we want, do something useful.
                    Run run = (Run)child;
                    Console.WriteLine(run.Text);
                }
            }
            //ExEnd:IndexChildNodes
        }
Beispiel #15
0
        public void ConvertNodeToHtmlWithDefaultOptions()
        {
            //ExStart
            //ExFor:Node.ToString(SaveFormat)
            //ExSummary:Exports the content of a node to string in HTML format using default options.
            Aspose.Words.Document doc = new Aspose.Words.Document(MyDir + "Document.doc");

            // Extract the last paragraph in the document to convert to HTML.
            Aspose.Words.Node node = doc.LastSection.Body.LastParagraph;

            // When ToString is called using the SaveFormat overload then conversion is executed using default save options.
            // When saving to HTML using default options the following settings are set:
            //   ExportImagesAsBase64 = true
            //   CssStyleSheetType = CssStyleSheetType.Inline
            //   ExportFontResources = false
            string nodeAsHtml = node.ToString(SaveFormat.Html);

            //ExEnd

            Assert.AreEqual("<p style=\"margin:0pt\"><span style=\"font-family:'Times New Roman'; font-size:12pt\">Hello World!</span></p>", nodeAsHtml);
        }
        //ExStart
        //ExFor:Paragraph.IsEndOfSection
        //ExId:InsertDocumentMain
        //ExSummary:This is a method that inserts contents of one document at a specified location in another document.
        /// <summary>
        /// Inserts content of the external document after the specified node.
        /// Section breaks and section formatting of the inserted document are ignored.
        /// </summary>
        /// <param name="insertAfterNode">Node in the destination document after which the content
        /// should be inserted. This node should be a block level node (paragraph or table).</param>
        /// <param name="srcDoc">The document to insert.</param>
        static void InsertDocument(Aspose.Words.Node insertAfterNode, Aspose.Words.Document srcDoc)
        {
            // Make sure that the node is either a paragraph or table.
            if ((!insertAfterNode.NodeType.Equals(NodeType.Paragraph)) &
                (!insertAfterNode.NodeType.Equals(NodeType.Table)))
            {
                throw new ArgumentException("The destination node should be either a paragraph or table.");
            }

            // We will be inserting into the parent of the destination paragraph.
            CompositeNode dstStory = insertAfterNode.ParentNode;

            // This object will be translating styles and lists during the import.
            NodeImporter importer = new NodeImporter(srcDoc, insertAfterNode.Document, ImportFormatMode.KeepSourceFormatting);

            // Loop through all sections in the source document.
            foreach (Aspose.Words.Section srcSection in srcDoc.Sections)
            {
                // Loop through all block level nodes (paragraphs and tables) in the body of the section.
                foreach (Aspose.Words.Node srcNode in srcSection.Body)
                {
                    // Let's skip the node if it is a last empty paragraph in a section.
                    if (srcNode.NodeType.Equals(NodeType.Paragraph))
                    {
                        Paragraph para = (Paragraph)srcNode;
                        if (para.IsEndOfSection && !para.HasChildNodes)
                        {
                            continue;
                        }
                    }

                    // This creates a clone of the node, suitable for insertion into the destination document.
                    Aspose.Words.Node newNode = importer.ImportNode(srcNode, true);

                    // Insert new node after the reference node.
                    dstStory.InsertAfter(newNode, insertAfterNode);
                    insertAfterNode = newNode;
                }
            }
        }
Beispiel #17
0
        public void EnumNextSibling()
        {
            Aspose.Words.Document doc = new Aspose.Words.Document();

            //ExStart
            //ExFor:CompositeNode.FirstChild
            //ExFor:Node.NextSibling
            //ExFor:Node.NodeTypeToString
            //ExFor:Node.NodeType
            //ExSummary:Shows how to enumerate immediate child nodes of a composite node using NextSibling. In this example we enumerate all paragraphs of a section body.
            // Get the section that we want to work on.
            Aspose.Words.Section section = doc.Sections[0];
            Body body = section.Body;

            // Loop starting from the first child until we reach null.
            for (Aspose.Words.Node node = body.FirstChild; node != null; node = node.NextSibling)
            {
                // Output the types of the nodes that we come across.
                Console.WriteLine(Aspose.Words.Node.NodeTypeToString(node.NodeType));
            }
            //ExEnd
        }
Beispiel #18
0
        public void CloneCompositeNode()
        {
            //ExStart
            //ExFor:Node
            //ExFor:Node.Clone
            //ExSummary:Shows how to clone composite nodes with and without their child nodes.
            // Create a new empty document.
            Aspose.Words.Document doc = new Aspose.Words.Document();

            // Add some text to the first paragraph
            Paragraph para = doc.FirstSection.Body.FirstParagraph;

            para.AppendChild(new Run(doc, "Some text"));

            // Clone the paragraph and the child nodes.
            Aspose.Words.Node cloneWithChildren = para.Clone(true);
            // Only clone the paragraph and no child nodes.
            Aspose.Words.Node cloneWithoutChildren = para.Clone(false);
            //ExEnd

            Assert.IsTrue(((CompositeNode)cloneWithChildren).HasChildNodes);
            Assert.IsFalse(((CompositeNode)cloneWithoutChildren).HasChildNodes);
        }
Beispiel #19
0
        public void RemoveChild()
        {
            Aspose.Words.Document doc = new Aspose.Words.Document();

            //ExStart
            //ExFor:CompositeNode.LastChild
            //ExFor:Node.PreviousSibling
            //ExFor:CompositeNode.RemoveChild
            //ExSummary:Demonstrates use of methods of Node and CompositeNode to remove a section before the last section in the document.
            // Document is a CompositeNode and LastChild returns the last child node in the Document node.
            // Since the Document can contain only Section nodes, the last child is the last section.
            Aspose.Words.Node lastSection = doc.LastChild;

            // Each node knows its next and previous sibling nodes.
            // Previous sibling of a section is a section before the specified section.
            // If the node is the first child, PreviousSibling will return null.
            Aspose.Words.Node sectionBeforeLast = lastSection.PreviousSibling;

            if (sectionBeforeLast != null)
            {
                doc.RemoveChild(sectionBeforeLast);
            }
            //ExEnd
        }
Beispiel #20
0
        public void ConvertNodeToHtmlWithSaveOptions()
        {
            //ExStart
            //ExFor:Node.ToString(SaveOptions)
            //ExSummary:Exports the content of a node to string in HTML format using custom specified options.
            Aspose.Words.Document doc = new Aspose.Words.Document(MyDir + "Document.doc");

            // Extract the last paragraph in the document to convert to HTML.
            Aspose.Words.Node node = doc.LastSection.Body.LastParagraph;

            // Create an instance of HtmlSaveOptions and set a few options.
            HtmlSaveOptions saveOptions = new HtmlSaveOptions();

            saveOptions.ExportHeadersFootersMode = ExportHeadersFootersMode.PerSection;
            saveOptions.ExportRelativeFontSize   = true;

            // Convert the document to HTML and return as a string. Pass the instance of HtmlSaveOptions to
            // to use the specified options during the conversion.
            string nodeAsHtml = node.ToString(saveOptions);

            //ExEnd

            Assert.AreEqual("<p style=\"margin:0pt\"><span style=\"font-family:'Times New Roman'\">Hello World!</span></p>", nodeAsHtml);
        }
        internal MergeField(FieldStart fieldStart)
        {
            if (fieldStart.Equals(null))
                throw new ArgumentNullException("fieldStart");
            if (!fieldStart.FieldType.Equals(FieldType.FieldMergeField))
                throw new ArgumentException("Field start type must be FieldMergeField.");

            mFieldStart = fieldStart;

            // Find the field separator node.
            mFieldSeparator = FindNextSibling(mFieldStart, NodeType.FieldSeparator);
            if (mFieldSeparator == null)
                throw new InvalidOperationException("Cannot find field separator.");

            // Find the field end node. Normally field end will always be found, but in the example document
            // there happens to be a paragraph break included in the hyperlink and this puts the field end
            // in the next paragraph. It will be much more complicated to handle fields which span several
            // paragraphs correctly, but in this case allowing field end to be null is enough for our purposes.
            mFieldEnd = FindNextSibling(mFieldSeparator, NodeType.FieldEnd);
        }
        internal Hyperlink(FieldStart fieldStart)
        {
            if (fieldStart == null)
                throw new ArgumentNullException("fieldStart");
            if (!fieldStart.FieldType.Equals(FieldType.FieldHyperlink))
                throw new ArgumentException("Field start type must be FieldHyperlink.");

            mFieldStart = fieldStart;

            // Find the field separator node.
            mFieldSeparator = FindNextSibling(mFieldStart, NodeType.FieldSeparator);
            if (mFieldSeparator == null)
                throw new InvalidOperationException("Cannot find field separator.");

            // Find the field end node. Normally field end will always be found, but in the example document
            // there happens to be a paragraph break included in the hyperlink and this puts the field end
            // in the next paragraph. It will be much more complicated to handle fields which span several
            // paragraphs correctly, but in this case allowing field end to be null is enough for our purposes.
            mFieldEnd = FindNextSibling(mFieldSeparator, NodeType.FieldEnd);

            // Field code looks something like [ HYPERLINK "http:\\www.myurl.com" ], but it can consist of several runs.
            string fieldCode = GetTextSameParent(mFieldStart.NextSibling, mFieldSeparator);
            Match match = gRegex.Match(fieldCode.Trim());
            mIsLocal = (match.Groups[1].Length > 0);	//The link is local if \l is present in the field code.
            mTarget = match.Groups[2].Value;
        }
Beispiel #23
0
        /// <summary>
        /// Converts a textbox to a table by copying the same content and formatting.
        /// Currently export to HTML will render the textbox as an image which looses any text functionality.
        /// This is useful to convert textboxes in order to retain proper text.
        /// </summary>
        /// <param name="textbox">The textbox shape to convert to a table</param>
        private static void ConvertTextboxToTable(Shape textBox)
        {
            if (textBox.StoryType != StoryType.Textbox)
            {
                throw new ArgumentException("Can only convert a shape of type textbox");
            }

            Aspose.Words.Document doc     = (Aspose.Words.Document)textBox.Document;
            Aspose.Words.Section  section = (Aspose.Words.Section)textBox.GetAncestor(NodeType.Section);

            // Create a table to replace the textbox and transfer the same content and formatting.
            Table table = new Table(doc);

            // Ensure that the table contains a row and a cell.
            table.EnsureMinimum();
            // Use fixed column widths.
            table.AutoFit(AutoFitBehavior.FixedColumnWidths);

            // A shape is inline level (within a paragraph) where a table can only be block level so insert the table
            // after the paragraph which contains the shape.
            Aspose.Words.Node shapeParent = textBox.ParentNode;
            shapeParent.ParentNode.InsertAfter(table, shapeParent);

            // If the textbox is not inline then try to match the shape's left position using the table's left indent.
            if (!textBox.IsInline && textBox.Left < section.PageSetup.PageWidth)
            {
                table.LeftIndent = textBox.Left;
            }

            // We are only using one cell to replicate a textbox so we can make use of the FirstRow and FirstCell property.
            // Carry over borders and shading.
            Row  firstRow  = table.FirstRow;
            Cell firstCell = firstRow.FirstCell;

            firstCell.CellFormat.Borders.Color     = textBox.StrokeColor;
            firstCell.CellFormat.Borders.LineWidth = textBox.StrokeWeight;
            firstCell.CellFormat.Shading.BackgroundPatternColor = textBox.Fill.Color;

            // Transfer the same height and width of the textbox to the table.
            firstRow.RowFormat.HeightRule = HeightRule.Exactly;
            firstRow.RowFormat.Height     = textBox.Height;
            firstCell.CellFormat.Width    = textBox.Width;
            table.AllowAutoFit            = false;

            // Replicate the textbox's horizontal alignment.
            TableAlignment horizontalAlignment;

            switch (textBox.HorizontalAlignment)
            {
            case HorizontalAlignment.Left:
                horizontalAlignment = TableAlignment.Left;
                break;

            case HorizontalAlignment.Center:
                horizontalAlignment = TableAlignment.Center;
                break;

            case HorizontalAlignment.Right:
                horizontalAlignment = TableAlignment.Right;
                break;

            default:
                // Most other options are left by default.
                horizontalAlignment = TableAlignment.Left;
                break;
            }

            table.Alignment = horizontalAlignment;
            firstCell.RemoveAllChildren();

            // Append all content from the textbox to the new table
            foreach (Aspose.Words.Node node in textBox.GetChildNodes(NodeType.Any, false).ToArray())
            {
                table.FirstRow.FirstCell.AppendChild(node);
            }

            // Remove the empty textbox from the document.
            textBox.Remove();
        }
Beispiel #24
0
        private void _BGWAbsenceNotification_DoWork(object sender, DoWorkEventArgs e)
        {
            #region 取得學生

            if (entityName.ToLower() == "student") //學生模式
            {
                SelectedStudents = K12.Data.Student.SelectByIDs(K12.Presentation.NLDPanels.Student.SelectedSource);
            }
            else if (entityName.ToLower() == "class") //班級模式
            {
                SelectedStudents = new List <StudentRecord>();
                foreach (StudentRecord each in Student.SelectByClassIDs(K12.Presentation.NLDPanels.Class.SelectedSource))
                {
                    if (each.Status != StudentRecord.StudentStatus.一般)
                    {
                        continue;
                    }

                    SelectedStudents.Add(each);
                }
            }
            else
            {
                throw new NotImplementedException();
            }

            SelectedStudents.Sort(new Comparison <StudentRecord>(CommonMethods.ClassSeatNoComparer));

            #endregion
            string reportName = "缺曠通知單";

            #region 快取資料

            //超級資訊物件
            Dictionary <string, StudentOBJ> StudentSuperOBJ = new Dictionary <string, StudentOBJ>();

            //合併列印的資料
            Dictionary <string, object> Allmapping   = new Dictionary <string, object>();
            Dictionary <string, string> ReversionDic = new Dictionary <string, string>();

            //所有學生ID
            List <string> allStudentID = new List <string>();

            //學生人數
            int currentStudentCount = 1;
            int totalStudentNumber  = 0;

            #region 取得 Period List
            List <string> periodList = new List <string>();
            Dictionary <string, string> TestPeriodList = new Dictionary <string, string>();
            int PeriodX = 1;
            Dictionary <string, object> mappingAccessory_copy = new Dictionary <string, object>();
            foreach (K12.Data.PeriodMappingInfo each in K12.Data.PeriodMapping.SelectAll())
            {
                if (!periodList.Contains(each.Name))
                {
                    periodList.Add(each.Name);
                }

                if (!TestPeriodList.ContainsKey(each.Name)) //節次<-->類別
                {
                    TestPeriodList.Add(each.Name, each.Type);
                }

                Allmapping.Add("節次" + PeriodX, each.Name);
                mappingAccessory_copy.Add("節次" + PeriodX, each.Name);
                ReversionDic.Add(each.Name, "節次" + PeriodX);
                PeriodX++;
            }
            #endregion

            #region 取得 Absence List
            Dictionary <string, string> TestAbsenceList = new Dictionary <string, string>(); //代碼替換(新)
            foreach (K12.Data.AbsenceMappingInfo each in K12.Data.AbsenceMapping.SelectAll())
            {
                if (!absenceList.ContainsKey(each.Name))
                {
                    absenceList.Add(each.Name, each.Abbreviation);
                }

                if (!TestAbsenceList.ContainsKey(each.Name)) //縮寫<-->假別
                {
                    TestAbsenceList.Add(each.Abbreviation, each.Name);
                }


                //Allmapping.Add("類型" + DefinedType + "缺曠" + DefinedAbsence,
            }
            #endregion

            //????使用者所選取的所有假別種類????
            List <string> userDefinedAbsenceList = new List <string>();

            int DefinedType = 1;
            foreach (string kind in configkeylist)
            {
                int DefinedAbsence = 1;
                Allmapping.Add("類型" + DefinedType, kind);

                foreach (string type in config[kind])
                {
                    Allmapping.Add("類型" + DefinedType + "缺曠" + DefinedAbsence, type);
                    Allmapping.Add("類型" + DefinedType + "縮寫" + DefinedAbsence, absenceList[type]);
                    DefinedAbsence++;

                    if (!userDefinedAbsenceList.Contains(type))
                    {
                        userDefinedAbsenceList.Add(type);
                    }
                }

                DefinedType++;
            }

            #region 取得所有學生ID
            foreach (StudentRecord aStudent in SelectedStudents)
            {
                //建立學生資訊,班級、座號、學號、姓名、導師
                string studentID = aStudent.ID;
                if (!StudentSuperOBJ.ContainsKey(studentID))
                {
                    StudentSuperOBJ.Add(studentID, new StudentOBJ());
                }

                //學生ID清單
                if (!allStudentID.Contains(studentID))
                {
                    allStudentID.Add(studentID);
                }

                StudentSuperOBJ[studentID].student       = aStudent;
                StudentSuperOBJ[studentID].TeacherName   = aStudent.Class != null ? (aStudent.Class.Teacher != null ? aStudent.Class.Teacher.Name : "") : "";
                StudentSuperOBJ[studentID].ClassName     = aStudent.Class != null ? aStudent.Class.Name : "";
                StudentSuperOBJ[studentID].SeatNo        = aStudent.SeatNo.HasValue ? aStudent.SeatNo.Value.ToString() : "";
                StudentSuperOBJ[studentID].StudentNumber = aStudent.StudentNumber;
                StudentSuperOBJ[studentID].ParentCode    = "";
            }
            #endregion

            #region 取得家長代碼
            // 因應 2019/11/14 弘文要求新epost  增加家長代碼抓取
            string ids = string.Join(",", allStudentID);

            string sql = "select student.id, student.parent_code, student.student_code, student.seat_no, student.name, class.grade_year, class.class_name from student";
            sql += " join class on class.id = student.ref_class_id where student.status in (1,2) and student.id in (" + ids + ") order by class.grade_year,class.display_order,class.class_name,student.seat_no";
            DataTable dt_parent_code = queryHelper.Select(sql);;

            foreach (DataRow row in dt_parent_code.Rows)
            {
                if (StudentSuperOBJ.ContainsKey("" + row["id"]))
                {
                    StudentSuperOBJ["" + row["id"]].ParentCode = "" + row["parent_code"];
                }
            }
            #endregion


            #region 取得所有學生缺曠紀錄,日期區間

            List <AttendanceRecord> attendanceList = K12.Data.Attendance.SelectByDate(SelectedStudents, obj.StartDate, obj.EndDate);

            if (attendanceList.Count == 0)
            {
                e.Cancel = true; //沒有缺曠資料
            }
            foreach (AttendanceRecord attendance in attendanceList)
            {
                if (!allStudentID.Contains(attendance.RefStudentID)) //如果是選取班級的學生
                {
                    continue;
                }

                string     studentID  = attendance.RefStudentID;
                DateTime   occurDate  = attendance.OccurDate;
                StudentOBJ studentOBJ = StudentSuperOBJ[studentID]; //取得這個物件

                foreach (AttendancePeriod attendancePeriod in attendance.PeriodDetail)
                {
                    string absenceType = attendancePeriod.AbsenceType; //假別
                    string periodName  = attendancePeriod.Period;      //節次

                    //是否為設定檔節次清單之中
                    if (!TestPeriodList.ContainsKey(periodName))
                    {
                        continue;
                    }

                    //是否為使用者選取之假別&類型
                    if (config.ContainsKey(TestPeriodList[periodName]))
                    {
                        if (config[TestPeriodList[periodName]].Contains(absenceType))
                        {
                            string PeriodAndAbsence = TestPeriodList[periodName] + "," + absenceType;
                            //區間統計
                            if (!studentOBJ.studentAbsence.ContainsKey(PeriodAndAbsence))
                            {
                                studentOBJ.studentAbsence.Add(PeriodAndAbsence, 0);
                            }

                            studentOBJ.studentAbsence[PeriodAndAbsence]++;

                            //明細記錄
                            if (!studentOBJ.studentAbsenceDetail.ContainsKey(occurDate.ToShortDateString()))
                            {
                                studentOBJ.studentAbsenceDetail.Add(occurDate.ToShortDateString(), new Dictionary <string, string>());
                            }

                            if (!studentOBJ.studentAbsenceDetail[occurDate.ToShortDateString()].ContainsKey(attendancePeriod.Period))
                            {
                                studentOBJ.studentAbsenceDetail[occurDate.ToShortDateString()].Add(attendancePeriod.Period, attendancePeriod.AbsenceType);
                            }
                        }
                    }
                }
            }

            #endregion

            List <string> DelStudent = new List <string>(); //列印的學生

            #region 條件1
            if (obj.ConditionName != "")                       //如果不等於空就是要判斷啦
            {
                foreach (string each1 in StudentSuperOBJ.Keys) //取出一個學生
                {
                    int  AbsenceCount = 0;
                    bool AbsenceBOOL  = false;
                    foreach (string each2 in StudentSuperOBJ[each1].studentAbsenceDetail.Keys)            //取出一天
                    {
                        foreach (string each3 in StudentSuperOBJ[each1].studentAbsenceDetail[each2].Keys) //取出一節內容
                        {
                            string each4 = StudentSuperOBJ[each1].studentAbsenceDetail[each2][each3];

                            if (TestPeriodList.ContainsKey(each3))
                            {
                                if (config.ContainsKey(TestPeriodList[each3]))
                                {
                                    if (obj.ConditionName == each4)
                                    {
                                        AbsenceCount++;
                                    }

                                    if (AbsenceCount >= int.Parse(obj.ConditionNumber))
                                    {
                                        AbsenceBOOL = true;
                                        if (!DelStudent.Contains(each1))
                                        {
                                            DelStudent.Add(each1); //把學生ID記下
                                        }
                                    }

                                    if (AbsenceBOOL)
                                    {
                                        break;
                                    }
                                }
                            }
                        }
                        if (AbsenceBOOL)
                        {
                            break;
                        }
                    }
                }
            }
            #endregion

            #region 條件2
            if (obj.ConditionName2 != "")                      //如果等於空就是直接全部印啦!!
            {
                foreach (string each1 in StudentSuperOBJ.Keys) //取出一個學生
                {
                    int  AbsenceCount = 0;
                    bool AbsenceBOOL  = false;
                    foreach (string each2 in StudentSuperOBJ[each1].studentAbsenceDetail.Keys)            //取出一天
                    {
                        foreach (string each3 in StudentSuperOBJ[each1].studentAbsenceDetail[each2].Keys) //取出一節內容
                        {
                            string each4 = StudentSuperOBJ[each1].studentAbsenceDetail[each2][each3];

                            if (TestPeriodList.ContainsKey(each3))
                            {
                                if (config.ContainsKey(TestPeriodList[each3]))
                                {
                                    if (obj.ConditionName2 == each4)
                                    {
                                        AbsenceCount++;
                                    }

                                    if (AbsenceCount >= int.Parse(obj.ConditionNumber2))
                                    {
                                        AbsenceBOOL = true;

                                        DelStudent.Add(each1); //把學生ID記下
                                    }

                                    if (AbsenceBOOL)
                                    {
                                        break;
                                    }
                                }
                                if (AbsenceBOOL)
                                {
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            #endregion

            #region 無條件則全部列印
            if (obj.ConditionName == "" && obj.ConditionName2 == "")
            {
                foreach (string each1 in StudentSuperOBJ.Keys) //取出一個學生
                {
                    if (!DelStudent.Contains(each1))
                    {
                        DelStudent.Add(each1);
                    }
                }
            }
            #endregion

            #region 取得所有學生缺曠紀錄,學期累計
            foreach (AttendanceRecord attendance in K12.Data.Attendance.SelectBySchoolYearAndSemester(Student.SelectByIDs(allStudentID), int.Parse(School.DefaultSchoolYear), int.Parse(School.DefaultSemester)))
            {
                //1(大於),0(等於)-1(小於)
                if (obj.EndDate.CompareTo(attendance.OccurDate) == -1)
                {
                    continue;
                }

                string     studentID  = attendance.RefStudentID;
                DateTime   occurDate  = attendance.OccurDate;
                StudentOBJ studentOBJ = StudentSuperOBJ[studentID]; //取得這個物件

                foreach (AttendancePeriod attendancePeriod in attendance.PeriodDetail)
                {
                    string absenceType = attendancePeriod.AbsenceType; //假別
                    string periodName  = attendancePeriod.Period;      //節次
                    if (!TestPeriodList.ContainsKey(periodName))
                    {
                        continue;
                    }

                    string PeriodAndAbsence = TestPeriodList[periodName] + "," + absenceType;
                    //區間統計
                    if (!studentOBJ.studentSemesterAbsence.ContainsKey(PeriodAndAbsence))
                    {
                        studentOBJ.studentSemesterAbsence.Add(PeriodAndAbsence, 0);
                    }

                    studentOBJ.studentSemesterAbsence[PeriodAndAbsence]++;
                }
            }

            #endregion

            #region 取得學生通訊地址資料
            foreach (AddressRecord record in Address.SelectByStudentIDs(allStudentID))
            {
                if (obj.ReceiveAddress == "戶籍地址")
                {
                    if (!string.IsNullOrEmpty(record.PermanentAddress))
                    {
                        StudentSuperOBJ[record.RefStudentID].address = record.Permanent.County + record.Permanent.Town + record.Permanent.District + record.Permanent.Area + record.Permanent.Detail;
                    }

                    if (!string.IsNullOrEmpty(record.PermanentZipCode))
                    {
                        StudentSuperOBJ[record.RefStudentID].ZipCode = record.PermanentZipCode;

                        if (record.PermanentZipCode.Length >= 1)
                        {
                            StudentSuperOBJ[record.RefStudentID].ZipCode1 = record.PermanentZipCode.Substring(0, 1);
                        }
                        if (record.PermanentZipCode.Length >= 2)
                        {
                            StudentSuperOBJ[record.RefStudentID].ZipCode2 = record.PermanentZipCode.Substring(1, 1);
                        }
                        if (record.PermanentZipCode.Length >= 3)
                        {
                            StudentSuperOBJ[record.RefStudentID].ZipCode3 = record.PermanentZipCode.Substring(2, 1);
                        }
                        if (record.PermanentZipCode.Length >= 4)
                        {
                            StudentSuperOBJ[record.RefStudentID].ZipCode4 = record.PermanentZipCode.Substring(3, 1);
                        }
                        if (record.PermanentZipCode.Length >= 5)
                        {
                            StudentSuperOBJ[record.RefStudentID].ZipCode5 = record.PermanentZipCode.Substring(4, 1);
                        }
                    }
                }
                else if (obj.ReceiveAddress == "聯絡地址")
                {
                    if (!string.IsNullOrEmpty(record.MailingAddress))
                    {
                        StudentSuperOBJ[record.RefStudentID].address = record.Mailing.County + record.Mailing.Town + record.Mailing.District + record.Mailing.Area + record.Mailing.Detail; //再處理
                    }
                    if (!string.IsNullOrEmpty(record.MailingZipCode))
                    {
                        StudentSuperOBJ[record.RefStudentID].ZipCode = record.MailingZipCode;

                        if (record.MailingZipCode.Length >= 1)
                        {
                            StudentSuperOBJ[record.RefStudentID].ZipCode1 = record.MailingZipCode.Substring(0, 1);
                        }
                        if (record.MailingZipCode.Length >= 2)
                        {
                            StudentSuperOBJ[record.RefStudentID].ZipCode2 = record.MailingZipCode.Substring(1, 1);
                        }
                        if (record.MailingZipCode.Length >= 3)
                        {
                            StudentSuperOBJ[record.RefStudentID].ZipCode3 = record.MailingZipCode.Substring(2, 1);
                        }
                        if (record.MailingZipCode.Length >= 4)
                        {
                            StudentSuperOBJ[record.RefStudentID].ZipCode4 = record.MailingZipCode.Substring(3, 1);
                        }
                        if (record.MailingZipCode.Length >= 5)
                        {
                            StudentSuperOBJ[record.RefStudentID].ZipCode5 = record.MailingZipCode.Substring(4, 1);
                        }
                    }
                }
                else if (obj.ReceiveAddress == "其他地址")
                {
                    if (!string.IsNullOrEmpty(record.Address1Address))
                    {
                        StudentSuperOBJ[record.RefStudentID].address = record.Address1.County + record.Address1.Town + record.Address1.District + record.Address1.Area + record.Address1.Detail; //再處理
                    }
                    if (!string.IsNullOrEmpty(record.Address1ZipCode))
                    {
                        StudentSuperOBJ[record.RefStudentID].ZipCode = record.Address1ZipCode;

                        if (record.Address1ZipCode.Length >= 1)
                        {
                            StudentSuperOBJ[record.RefStudentID].ZipCode1 = record.Address1ZipCode.Substring(0, 1);
                        }
                        if (record.Address1ZipCode.Length >= 2)
                        {
                            StudentSuperOBJ[record.RefStudentID].ZipCode2 = record.Address1ZipCode.Substring(1, 1);
                        }
                        if (record.Address1ZipCode.Length >= 3)
                        {
                            StudentSuperOBJ[record.RefStudentID].ZipCode3 = record.Address1ZipCode.Substring(2, 1);
                        }
                        if (record.Address1ZipCode.Length >= 4)
                        {
                            StudentSuperOBJ[record.RefStudentID].ZipCode4 = record.Address1ZipCode.Substring(3, 1);
                        }
                        if (record.Address1ZipCode.Length >= 5)
                        {
                            StudentSuperOBJ[record.RefStudentID].ZipCode5 = record.Address1ZipCode.Substring(4, 1);
                        }
                    }
                }
            }
            #endregion

            #region 取得學生監護人父母親資料
            foreach (ParentRecord record in Parent.SelectByStudentIDs(allStudentID))
            {
                StudentSuperOBJ[record.RefStudentID].CustodianName = record.CustodianName;
                StudentSuperOBJ[record.RefStudentID].FatherName    = record.FatherName;
                StudentSuperOBJ[record.RefStudentID].MotherName    = record.MotherName;
            }
            //dsrsp = JHSchool.Compatibility.Feature.QueryStudent.GetMultiParentInfo(allStudentID.ToArray());
            //foreach (XmlElement var in dsrsp.GetContent().GetElements("ParentInfo"))
            //{
            //    string studentID = var.GetAttribute("StudentID");

            //    studentInfo[studentID].Add("CustodianName", var.SelectSingleNode("CustodianName").InnerText);
            //    studentInfo[studentID].Add("FatherName", var.SelectSingleNode("FatherName").InnerText);
            //    studentInfo[studentID].Add("MotherName", var.SelectSingleNode("MotherName").InnerText);
            //}
            #endregion

            #endregion

            Document template = new Document(obj.Template);

            #region 缺曠類別部份
            int columnNumber = 0;

            foreach (List <string> var in config.Values)
            {
                columnNumber += var.Count;
            }
            #endregion

            #region 產生報表

            Document doc = new Document();
            doc.Sections.Clear();
            paperForStudent = new SmartSchool.ePaper.ElectronicPaper("缺曠通知單_" + DateTime.Now.Year + DateTime.Now.Month.ToString().PadLeft(2, '0') + DateTime.Now.Day.ToString().PadLeft(2, '0'), School.DefaultSchoolYear, School.DefaultSemester, SmartSchool.ePaper.ViewerType.Student);

            DataTable dt = new DataTable();

            // 2020/01/09 穎驊修正,因應郵局格式要求說明文件中,收件人的姓名、郵遞區號和地址,有規定的欄位名稱(CN,POSTALCODE,POSTALADDRESS),手動填入
            dt.Columns.Add("CN");
            dt.Columns.Add("POSTALCODE");
            dt.Columns.Add("POSTALADDRESS");

            foreach (string studentID in StudentSuperOBJ.Keys)
            {
                Dictionary <string, object> mappingAccessory = new Dictionary <string, object>();
                foreach (string each in mappingAccessory_copy.Keys)
                {
                    mappingAccessory.Add(each, mappingAccessory_copy[each]);
                }

                StudentOBJ eachStudentInfo = StudentSuperOBJ[studentID];

                //合併列印的資料
                Dictionary <string, object> mapping = new Dictionary <string, object>();

                if (!DelStudent.Contains(studentID)) //如果不包含在內,就離開
                {
                    continue;
                }

                if (obj.PrintHasRecordOnly)
                {
                    //明細等於0
                    if (eachStudentInfo.studentAbsenceDetail.Count == 0)
                    {
                        currentStudentCount++;
                        continue;
                    }
                }

                Document eachSection = new Document();
                eachSection.Sections.Clear();
                eachSection.Sections.Add(eachSection.ImportNode(template.Sections[0], true));

                MemoryStream          accessoryMemory;
                Aspose.Words.Document accessoryDoc;

                //學生資料
                mappingAccessory.Add("學生姓名", eachStudentInfo.student.Name);
                mappingAccessory.Add("班級", eachStudentInfo.ClassName);
                mappingAccessory.Add("座號", eachStudentInfo.SeatNo);
                mappingAccessory.Add("學號", eachStudentInfo.StudentNumber);
                mappingAccessory.Add("導師", eachStudentInfo.TeacherName);
                mappingAccessory.Add("學年度", School.DefaultSchoolYear);
                mappingAccessory.Add("學期", School.DefaultSemester);
                mappingAccessory.Add("資料期間", obj.StartDate.ToShortDateString() + " 至 " + obj.EndDate.ToShortDateString());
                //懲戒明細
                bool IsAccessory = false;

                //學校資訊
                mapping.Add("學校名稱", School.ChineseName);
                mapping.Add("學校地址", School.Address);
                mapping.Add("學校電話", School.Telephone);

                //學生資料
                mapping.Add("學生姓名", eachStudentInfo.student.Name);
                mapping.Add("班級", eachStudentInfo.ClassName);
                mapping.Add("座號", eachStudentInfo.SeatNo);
                mapping.Add("學號", eachStudentInfo.StudentNumber);
                mapping.Add("導師", eachStudentInfo.TeacherName);
                mapping.Add("資料期間", obj.StartDate.ToShortDateString() + " 至 " + obj.EndDate.ToShortDateString());

                // 2019/11/12 穎驊註解 本專案為弘文於本學期提出來的需求,增加家長代碼
                mapping.Add("家長代碼", eachStudentInfo.ParentCode);

                //收件人資料
                if (obj.ReceiveName == "監護人姓名")
                {
                    mapping.Add("收件人姓名", eachStudentInfo.CustodianName);
                }
                else if (obj.ReceiveName == "父親姓名")
                {
                    mapping.Add("收件人姓名", eachStudentInfo.FatherName);
                }
                else if (obj.ReceiveName == "母親姓名")
                {
                    mapping.Add("收件人姓名", eachStudentInfo.MotherName);
                }
                else
                {
                    mapping.Add("收件人姓名", eachStudentInfo.student.Name);
                }

                //收件人地址資料
                mapping.Add("收件人地址", eachStudentInfo.address);
                mapping.Add("郵遞區號", eachStudentInfo.ZipCode);
                mapping.Add("0", eachStudentInfo.ZipCode1);
                mapping.Add("1", eachStudentInfo.ZipCode2);
                mapping.Add("2", eachStudentInfo.ZipCode3);
                mapping.Add("4", eachStudentInfo.ZipCode4);
                mapping.Add("5", eachStudentInfo.ZipCode5);

                mapping.Add("學年度", School.DefaultSchoolYear);
                mapping.Add("學期", School.DefaultSemester);

                //缺曠學期統計部份
                int columnIndex      = 1;
                int DefinedTypeCount = 1;
                foreach (string attendanceType in configkeylist)
                {
                    int DefinedAbsenceCount = 1;

                    foreach (string absenceType in config[attendanceType])
                    {
                        string dataValue         = "0";
                        string semesterDataValue = "0";
                        string PeriodAndAbsence  = attendanceType + "," + absenceType;
                        //本期統計
                        if (eachStudentInfo.studentAbsence.ContainsKey(PeriodAndAbsence))
                        {
                            dataValue = eachStudentInfo.studentAbsence[PeriodAndAbsence].ToString();
                        }
                        //學期統計
                        if (eachStudentInfo.studentSemesterAbsence.ContainsKey(PeriodAndAbsence))
                        {
                            semesterDataValue = eachStudentInfo.studentSemesterAbsence[PeriodAndAbsence].ToString();
                        }

                        mapping.Add("類型" + DefinedTypeCount + "本期" + DefinedAbsenceCount, dataValue);
                        mapping.Add("類型" + DefinedTypeCount + "學期" + DefinedAbsenceCount, semesterDataValue);
                        DefinedAbsenceCount++;
                        columnIndex++;
                    }
                    DefinedTypeCount++;
                }

                // 2020/02/07 嘉詮與學校後 確立 格式固定要有 日期1~日期12 且每日節次1~12,故總變數為日期1節次1 ~ 日期12節次12
                for (int date = 1; date <= 12; date++)
                {
                    mapping.Add("日期" + date, "");

                    for (int peroid = 1; peroid <= 12; peroid++)
                    {
                        mapping.Add("日期" + date + "節次" + peroid, "");
                    }
                }


                //缺曠明細
                int DateCount = 1;
                foreach (string each in eachStudentInfo.studentAbsenceDetail.Keys)
                {
                    int Period = 1;
                    //資料數大於10,透過附件列印
                    if (DateCount <= 12)
                    {
                        if (mapping.ContainsKey("日期" + DateCount))
                        {
                            mapping["日期" + DateCount] = Switching(each);
                        }
                        else
                        {
                            mapping.Add("日期" + DateCount, Switching(each));
                        }
                    }

                    else
                    {
                        mappingAccessory.Add("日期" + DateCount, Switching(each));
                    }


                    //取得節次清單,一一檢查是否有資料要填
                    foreach (string Date in eachStudentInfo.studentAbsenceDetail[each].Keys)
                    {
                        string detail = eachStudentInfo.studentAbsenceDetail[each][Date];

                        if (absenceList.ContainsKey(detail))
                        {
                            if (ReversionDic.ContainsKey(Date))
                            {
                                if (DateCount <= 12) //資料數大於10,透過附件列印
                                {
                                    if (mapping.ContainsKey("日期" + DateCount + ReversionDic[Date]))
                                    {
                                        mapping["日期" + DateCount + ReversionDic[Date]] = absenceList[detail];
                                    }
                                    else
                                    {
                                        mapping.Add("日期" + DateCount + ReversionDic[Date], absenceList[detail]);
                                    }

                                    Period++;
                                }
                                else
                                {
                                    mappingAccessory.Add("日期" + DateCount + ReversionDic[Date], absenceList[detail]);
                                    IsAccessory = true;
                                    Period++;
                                }
                            }
                        }
                    }

                    DateCount++;
                }



                //學生個人資料
                string[] keys   = new string[mapping.Count];
                object[] values = new object[mapping.Count];
                int      i      = 0;
                foreach (string key in mapping.Keys)
                {
                    keys[i]     = key;
                    values[i++] = mapping[key];
                }
                eachSection.MailMerge.Execute(keys, values);


                //整體資料
                string[] Allkeys   = new string[Allmapping.Count];
                object[] Allvalues = new object[Allmapping.Count];
                int      t         = 0;
                foreach (string key in Allmapping.Keys)
                {
                    Allkeys[t]     = key;
                    Allvalues[t++] = Allmapping[key];
                }

                eachSection.MailMerge.Execute(Allkeys, Allvalues);
                eachSection.MailMerge.DeleteFields();

                #region epost 使用



                // 將對應功能變數 套入dt
                foreach (string key in mapping.Keys)
                {
                    if (!dt.Columns.Contains(key))
                    {
                        dt.Columns.Add(key);
                    }
                }

                foreach (string key in Allmapping.Keys)
                {
                    if (!dt.Columns.Contains(key))
                    {
                        dt.Columns.Add(key);
                    }
                }

                DataRow row = dt.NewRow();

                row["CN"]            = mapping["收件人姓名"];
                row["POSTALCODE"]    = mapping["郵遞區號"];
                row["POSTALADDRESS"] = mapping["收件人地址"];

                foreach (string key in mapping.Keys)
                {
                    row[key] = mapping[key];
                }

                foreach (string key in Allmapping.Keys)
                {
                    row[key] = Allmapping[key];
                }



                dt.Rows.Add(row);
                #endregion


                if (IsAccessory)
                {
                    accessoryMemory = new MemoryStream(Properties.Resources.缺曠通知單_附件一);
                    accessoryDoc    = new Aspose.Words.Document(accessoryMemory);

                    string[] keysAccessory   = new string[mappingAccessory.Count];
                    object[] valuesAccessory = new object[mappingAccessory.Count];
                    int      xx = 0;
                    foreach (string key in mappingAccessory.Keys)
                    {
                        keysAccessory[xx]     = key;
                        valuesAccessory[xx++] = mappingAccessory[key];
                    }

                    accessoryDoc.MailMerge.CleanupOptions = Aspose.Words.Reporting.MailMergeCleanupOptions.RemoveEmptyParagraphs;
                    accessoryDoc.MailMerge.Execute(keysAccessory, valuesAccessory);
                    accessoryDoc.MailMerge.DeleteFields(); //刪除未合併之內容

                    Aspose.Words.Node eachSectionaccessory = accessoryDoc.Sections[0].Clone();
                    eachSection.Sections.Add(eachSection.ImportNode(eachSectionaccessory, true));

                    MemoryStream stream = new MemoryStream();
                    eachSection.Save(stream, SaveFormat.Doc);
                    paperForStudent.Append(new PaperItem(PaperFormat.Office2003Doc, stream, eachStudentInfo.student.ID));
                }
                else
                {
                    MemoryStream stream = new MemoryStream();
                    eachSection.Save(stream, SaveFormat.Doc);
                    paperForStudent.Append(new PaperItem(PaperFormat.Office2003Doc, stream, eachStudentInfo.student.ID));
                }

                foreach (Aspose.Words.Section each in eachSection.Sections)
                {
                    Aspose.Words.Node eachSectionNode = each.Clone();
                    doc.Sections.Add(doc.ImportNode(eachSectionNode, true));
                }

                //回報進度
                _BGWAbsenceNotification.ReportProgress((int)(((double)currentStudentCount++ *100.0) / (double)totalStudentNumber));
            }

            #endregion

            #region 產生學生清單

            Aspose.Cells.Workbook wb = new Aspose.Cells.Workbook();
            if (obj.PrintStudentList)
            {
                int CountRow = 0;
                wb.Worksheets[0].Cells[CountRow, 0].PutValue("班級");
                wb.Worksheets[0].Cells[CountRow, 1].PutValue("座號");
                wb.Worksheets[0].Cells[CountRow, 2].PutValue("學號");
                wb.Worksheets[0].Cells[CountRow, 3].PutValue("學生姓名");
                wb.Worksheets[0].Cells[CountRow, 4].PutValue("收件人姓名");
                wb.Worksheets[0].Cells[CountRow, 5].PutValue("地址");
                wb.Worksheets[0].Cells[CountRow, 6].PutValue("家長代碼");
                CountRow++;
                foreach (string each in StudentSuperOBJ.Keys)
                {
                    if (!DelStudent.Contains(each)) //如果不包含在內,就離開
                    {
                        continue;
                    }

                    if (obj.PrintHasRecordOnly)
                    {
                        //明細等於0
                        if (StudentSuperOBJ[each].studentAbsenceDetail.Count == 0)
                        {
                            currentStudentCount++;
                            continue;
                        }
                    }

                    wb.Worksheets[0].Cells[CountRow, 0].PutValue(StudentSuperOBJ[each].ClassName);
                    wb.Worksheets[0].Cells[CountRow, 1].PutValue(StudentSuperOBJ[each].SeatNo);
                    wb.Worksheets[0].Cells[CountRow, 2].PutValue(StudentSuperOBJ[each].StudentNumber);
                    wb.Worksheets[0].Cells[CountRow, 3].PutValue(StudentSuperOBJ[each].student.Name);
                    //收件人資料
                    if (obj.ReceiveName == "監護人姓名")
                    {
                        wb.Worksheets[0].Cells[CountRow, 4].PutValue(StudentSuperOBJ[each].CustodianName);
                    }
                    else if (obj.ReceiveName == "父親姓名")
                    {
                        wb.Worksheets[0].Cells[CountRow, 4].PutValue(StudentSuperOBJ[each].FatherName);
                    }
                    else if (obj.ReceiveName == "母親姓名")
                    {
                        wb.Worksheets[0].Cells[CountRow, 4].PutValue(StudentSuperOBJ[each].MotherName);
                    }
                    else
                    {
                        wb.Worksheets[0].Cells[CountRow, 4].PutValue(StudentSuperOBJ[each].student.Name);
                    }

                    wb.Worksheets[0].Cells[CountRow, 5].PutValue(StudentSuperOBJ[each].ZipCode + " " + StudentSuperOBJ[each].address);
                    wb.Worksheets[0].Cells[CountRow, 6].PutValue(StudentSuperOBJ[each].ParentCode);
                    CountRow++;
                }
                wb.Worksheets[0].AutoFitColumns();
            }
            #endregion

            //是否上傳電子報表
            if (obj.PaperUpdate)
            {
                SmartSchool.ePaper.DispatcherProvider.Dispatch(paperForStudent);
            }

            string path  = Path.Combine(Application.StartupPath, "Reports");
            string path2 = Path.Combine(Application.StartupPath, "Reports");
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            path     = Path.Combine(path, reportName + ".docx");
            path2    = Path.Combine(path2, reportName + "(學生清單).xlsx");
            e.Result = new object[] { reportName, path, doc, path2, obj.PrintStudentList, wb, dt };
        }