I am trying to create a function that creates one (1) PDF-invoice for each distinct value of a property in a List I am looping through (using PDFSharp).
I grab the value of the string, and want to use it as header of the invoices (it's the name of the business getting invoiced).
To illustrate: In the following table, I would like to get the value of LicenseHolder1 (once), LicenseHolder2 (once) and LicenseHolder3 (once).
| ID | LicenseHolderID | Value1 | Value2 | Value3 |
|---|---|---|---|---|
| 1 | LicenseHolder1 | 66 | 44 | UF-2107 |
| 2 | LicenseHolder2 | 22 | 25 | UF-2107 |
| 3 | LicenseHolder2 | 62 | 24 | UF-2107 |
| 4 | LicenseHolder3 | 82 | 12 | UF-2107 |
| 5 | LicenseHolder3 | 6 | 77 | UF-2107 |
| 6 | LicenseHolder3 | 15 | 62 | UF-2107 |
This is the method I am using:
using (SqlConnection con = new(ConnectionString.connectionString))
using (SqlCommand cmd = new("spCreateInvoice", con) {CommandType = CommandType.StoredProcedure})
using (SqlDataAdapter da = new(cmd))
// this is the name of my SQL table
using (DataTable dt = new("tblTripsPerMonth"))
using (DataSet ds = new()) {
con.Open();
da.Fill(dt);
ds.Tables.Add(dt);
/* adding the SQL table rows to my ObservableCollection (PaidTrips),
which is bound to properties in my holder class (PaidTrip): */
foreach (DataRow dr in ds.Tables[0].Rows {
PaidTrips.Add(new PaidTrip {
LicenseHolderID = dr[0].ToString(),
Value1 = (decimal)dr[1],
Value2 = (decimal)dr[2],
Value3 = dr[3].ToString(),
});
// Now I am instantiating a list, so that I can group
List<PaidTrip> paidTrip = PaidTrips
.GroupBy(p => new {p.LicenseHolderID})
.Select(g => g.First())
.ToList();
// this is copied code from another question, and this is where I fall of
foreach (PaidTrip PaidTrips in paidTrip) {
foreach (var LicenseHolderID in PaidTrips.GetType().GetProperties()) {
string n = LicenseHolderID.GetValue(PaidTrips).ToString();
If I after this grab string n and pass it into, let's say, a MessageBox.Show, it displays LicenseHolder1, as it should.
But, if I try to pass it into the PDF, like this...
(continued from last code-block)
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
PdfDocument pdf = new();
PdfPage page = pdf.AddPage();
XGraphics gfx = XGraphics.FromPdfPage(page);
// drawing in the string value
gfx.DrawString(n, new XFont("Arial", 40, XFontStyle.Bold), myColor, new XPoint(40, 250));
// saving the PDF
pdf.Save("C:\File\Path\TestPDF.pdf");
}
}
}
}
...the PDF is created, but the string I drew is not filled with LicenseHolder1, but rather, with (seemingly) random values of the other columns (like 66, UF-2107 or 77). How come?
(Oh, and I know that this code only creates one (1) PDF-file, I need several (one for each distinct value in the LicenseHolderID column -- but that's an issue for another day)
Is there an id column in your datatable as shown above? would your column zero not be taking an id there?
foreach (DataRow dr in ds.Tables[0].Rows {
PaidTrips.Add(new PaidTrip {
LicenseHolderID = dr[0].ToString(),
Value1 = (decimal)dr[1],
Value2 = (decimal)dr[2],
Value3 = dr[3].ToString(),
});
If your grouping by LicenseHolderID your selecting the first element of the grouped result. Is that intended?
List<PaidTrip> paidTrip = PaidTrips
.GroupBy(p => new {p.LicenseHolderID})
.Select(g => g.First())
.ToList();
This would essentialy return one new Object Containing multiple Paid Trip objects containing the same LicenseHolderID.
Usually if you want to use the string name of the group you can reference the key value.
paidTrip.Key.ToString();
might be better to use,
var paidTrip = PaidTrips
.GroupBy(p => new {p.LicenseHolderID})
.ToList();
foreach (var tripFound in paidTrip)
{
string tripId = tripFound.Key.ToString();
//Generate your PDF File.
}
This should give you one file per group. Apologies if i've picked you up wrong.
I don't understand what you are trying to accomplish in these nested foreach loops
foreach (PaidTrip PaidTrips in paidTrip) {
foreach (var LicenseHolderID in PaidTrips.GetType().GetProperties()) {
//...
}
}
paidTrip should be an IEnumerable<PaidTrip> that represents the first PaidTrip by each company, so maybe renaming the variable to firstPaidTrips would help clarify things in your code, then your outer foreach loop it could be
foreach (var paidTrip in firstPaidTrips)
Then it will be more clear that each variable in that foreach loop is a singular paidTrip
To get the LicenseHolderID for that paid trip, you just need to access that property directly.
foreach (var paidTrip in firstPaidTrips)
{
var n = paidTrip.LicenseHolderID;
//rest of the code is the same without that inner foreach loop.
}
That inner foreach loop looks like you were trying to use reflection to get all the properties on an unknown type object, but from your example code it looks like you know what the object type is, and you should be able to just grab the property from the object PaidTrip
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With