如何在MigraDoc中获取表格单元格值并计算Costs列总和
Got it, let's fix this up for you. The main issue here is that you don't need to jump through hoops with GetValue() to pull values back from MigraDoc cells—since you already have access to the raw TicketView1 data, you can calculate the total as you build your table rows, then just drop that total into your final "TOTAL" row. Here's the step-by-step adjustment:
Step 1: Initialize a total variable
Before your foreach loop, declare a decimal variable to track the sum of costs (decimal is better than double for currency to avoid rounding errors):
decimal totalCosts = 0m;
Step 2: Calculate the total as you add data rows
First, fix your existing code: right now you're only setting the Costs cell after the foreach loop, which means only the last row will have a value. Move that cell assignment inside the loop, and add the ticket's cost to your total each time.
Assuming your TicketView1 has a cost property (let's say ticket.cost), adjust the loop like this:
//define a row of data in the table foreach (TicketView1 ticket in SampleTickets) { row = table.AddRow(); cell = row.Cells[0]; cell.AddParagraph(ticket.customer_name); cell = row.Cells[1]; cell.AddParagraph(ticket.date_created.ToString("MM/dd/yyyy")); cell = row.Cells[2]; cell.AddParagraph(ticket.description); cell = row.Cells[3]; cell.AddParagraph(ticket.due_date.ToString("MM/dd/yyyy")); cell = row.Cells[4]; cell.AddParagraph(ticket.billable_hrs.ToString()); // Handle Costs column and update total cell = row.Cells[5]; // Parse the ticket's cost (adjust if your ticket stores cost differently) decimal ticketCost = ticket.cost; // If cost is already a decimal // If cost is stored as a string with $, use: // decimal ticketCost = decimal.Parse(ticket.cost.Replace("$", "")); totalCosts += ticketCost; // Format and add to cell cell.AddParagraph($"${ticketCost.ToString("0.00")}"); }
Step 3: Plug the total into your TOTAL row
When you create the final TOTAL row, just use your totalCosts variable to populate the Costs cell:
//add total row = table.AddRow(); row.Cells[0].Borders.Visible = false; row.Cells[0].AddParagraph("TOTAL:"); row.Cells[0].Format.Font.Bold = true; row.Cells[0].Format.Alignment = ParagraphAlignment.Right; row.Cells[0].MergeRight = 4; // Add total to Costs cell cell = row.Cells[5]; cell.AddParagraph($"${totalCosts.ToString("0.00")}"); cell.Format.Font.Bold = true; // Optional: make total bold for emphasis
Why not use GetValue()?
MigraDoc's GetValue() method is designed for more advanced scenarios like retrieving values from form fields or dynamic content after the document is built. Since you're generating the table from your own data source (SampleTickets), calculating the total directly in your code is far simpler and more efficient—you don't need to "read back" values from the cells you just created.
Full Modified Code
Here's the complete adjusted code for context:
//define header of table Row row = table.AddRow(); row.HeadingFormat = true; Cell cell = row.Cells[0]; cell.AddParagraph("Customer Name"); cell.Format.Font.Bold = true; cell = row.Cells[1]; cell.AddParagraph("Date Created"); cell.Format.Font.Bold = true; cell = row.Cells[2]; cell.AddParagraph("Description"); cell.Format.Font.Bold = true; cell = row.Cells[3]; cell.AddParagraph("Due Date"); cell.Format.Font.Bold = true; cell = row.Cells[4]; cell.AddParagraph("Billable Hours"); cell.Format.Font.Bold = true; cell = row.Cells[5]; cell.AddParagraph("Costs"); cell.Format.Font.Bold = true; // Initialize total costs variable decimal totalCosts = 0m; //define a row of data in the table foreach (TicketView1 ticket in SampleTickets) { row = table.AddRow(); cell = row.Cells[0]; cell.AddParagraph(ticket.customer_name); cell = row.Cells[1]; cell.AddParagraph(ticket.date_created.ToString("MM/dd/yyyy")); cell = row.Cells[2]; cell.AddParagraph(ticket.description); cell = row.Cells[3]; cell.AddParagraph(ticket.due_date.ToString("MM/dd/yyyy")); cell = row.Cells[4]; cell.AddParagraph(ticket.billable_hrs.ToString()); // Handle Costs column and update total cell = row.Cells[5]; decimal ticketCost = ticket.cost; // Adjust based on your actual ticket property totalCosts += ticketCost; cell.AddParagraph($"${ticketCost.ToString("0.00")}"); } //add invisible row as a space line to the table row = table.AddRow(); row.Borders.Visible = false; //add the subtotal row row = table.AddRow(); row.Cells[0].Borders.Visible = false; row.Cells[0].AddParagraph("Sub Total:"); row.Cells[0].Format.Font.Bold = true; row.Cells[0].Format.Alignment = ParagraphAlignment.Right; row.Cells[0].MergeRight = 4; cell = row.Cells[5]; cell.AddParagraph($"${totalCosts.ToString("0.00")}"); // Add subtotal here too if needed //add tax row row = table.AddRow(); row.Cells[0].Borders.Visible = false; row.Cells[0].AddParagraph("TAX:"); row.Cells[0].Format.Font.Bold = true; row.Cells[0].Format.Alignment = ParagraphAlignment.Right; row.Cells[0].MergeRight = 4; // If you need to calculate tax, add that logic here (e.g., decimal tax = totalCosts * 0.08m;) //add total row = table.AddRow(); row.Cells[0].Borders.Visible = false; row.Cells[0].AddParagraph("TOTAL:"); row.Cells[0].Format.Font.Bold = true; row.Cells[0].Format.Alignment = ParagraphAlignment.Right; row.Cells[0].MergeRight = 4; cell = row.Cells[5]; // If including tax, use totalCosts + tax here cell.AddParagraph($"${totalCosts.ToString("0.00")}"); cell.Format.Font.Bold = true;
内容的提问来源于stack exchange,提问作者Randy Goldsmith

