遍历列表,但无法访问不同的项目值
Iterating through a list, but can't access distinct item values
我正在使用 PDFsharp 创建发票。
这是我的 SQL table (tblTripsPerMonth
):
我已将其绑定到 ObservableCollection
(PaidTrips
)。
目标是为 LicenseHolderID
列中每个不同的“CompanyName”创建一 (1) 个 PDF。
为此,我转换为 List
,并按 LicenseHolderID
.
分组
var paidTrips = PaidTrips
.GroupBy(p => new {
p.LicenseHolderID
})
.ToList();
之后,我用 foreach
循环遍历列表:
foreach (var trip in paidTrips) {
// I grab the distinct name
string licenseholder = trip.Key.LicenseHolderID.ToString();
// I summarize many of the columns
decimal totalPayment = trip.Sum(x => x.Payment);
decimal totalPaymentNet = trip.Sum(x => x.Payment);
decimal totalOrderFee = trip.Sum(x => x.Payment);
decimal totalPaymentFee = trip.Sum(x => x.Payment);
// I grab the first value of some other columns, which won't change
string licenseholderInvoiceID = trip.Select(x => x.LicenseHolderInvoiceID).FirstOrDefault().ToString();
string ridelRegionInvoiceID = trip.Select(x => x.RidelRegionInvoiceID ).FirstOrDefault().ToString();
// Creating PDF document using PDFsharp:
// PDFsharp code
// PDFsharp code
// PDFsharp code
}
我能够创建一个 PDF 文档,每个不同的 LicenseHolderID
,通过将 licenseHolderID
字符串添加到 PDFsharps document.Save()
的文件路径。
但是我无法用我需要的所有信息填写 PDF 文档。
我有汇总金额 - good,因为我绝对需要显示完整的发票金额。
但是——我还需要详细说明。我 没有 每个 VehicleID
的金额。
对于“CompanyName1”,将是 AG4203000002 和 AG4203000003,以及它们对应的行数据。
我确实这样做了...
IEnumerable<string> vehicleIds = trip
.Select(x => x.VehicleID)
.Distinct()
.ToArray();
string vehicle = string.Join(", ", vehicleIds);
...为了将 VehicleID
个不同的值彼此分开。
然后我将 string vehicle
放入 PDFsharp 中,将文本绘制到 PDF (DrawString
):
gfx.DrawString(vehicle, /* font and color customization */);
这为我提供了每个 LicenseHolderID
的正确数量的 VehicleID
,但在一个长字符串中...不是最优的。
这让我想到了我的问题: A):我需要携带与VehicleID
中的不同车辆,以便我可以在我的 PDF 中填写详细信息,而不仅仅是汇总值,以及 B):如果 的解决方案A) 涉及摆脱又长又难懂的字符串 (vehicle
),那将是最佳选择,如果不是 - 那也没关系。
更新(添加来自@Dai 的回答的代码):
// PaidTrip = My holder class, which I've bound to a ObservableCollection (PaidTrips)
var paidTrips = PaidTrips.ToList(); // I was unsure about this one
IEnumerable<IGrouping<String, PaidTrip>> tripsGroupedByCompany = paidTrips.GroupBy(pt => pt.LicenseHolderID);
foreach (IGrouping<String, PaidTrip>> companyGroup in tripsGroupedByCompany) {
string licenseHolderId = companyGroup.Key;
gfx.DrawString(/* code goes foo */);
// I tried adding Key here, but that gave me a squiggly under "t.VehicleID"
var groupedByVehicle = companyGroup.GroupBy(t => t.VehicleID);
foreach (IGrouping<String, PaidTrip> vehicleGroup in groupedByVehicle) {
// This is where I get a red squiggly; under Key
String vehicleId = groupedByVehicle.Key;
gfx.DrawString(/* code goes foo */);
foreach (PaidTrip trip in vehicleGroup) {
gfx.DrawString(/* code goes foo */);
}
}
}
这是错误:
CS1061: IEnumerable<IGrouping<string, PaidTrip>> does not contain a definition for 'Key' and no accessible extension method 'Key' accepting a first argument of type 'IEnumerable<IGrouping<string, PaidTrip>>' could be found (are you missing a using directive or an assembly reference?)
I need to bring along the row data of the other columns pertaining to the distinct vehicles in VehicleId
, so that I can fill in details in my PDFs, and not just the summarized values.
如果我没理解错的话,对于每家公司 (LicenseHolderId
),您需要他们的相关 Trip
对象,但按 VehicleId
分组 - 这很简单,只需添加另一个 GroupBy
- 你可以在内部迭代它们 foreach
:
List<Trip> paidTrips = ...
IEnumerable< IGrouping<String,Trip> > tripsGroupedByCompany = paidTrips.GroupBy( pt => pt.LicenseHolderId );
foreach( IGrouping<String,Trip> companyGroup in tripsGroupedByCompany )
{
String licenseHolderId = companyGroup.Key;
gfx.DrawString( "Company: " + licenseHolderId + "\r\n" );
var groupedByVehicle = companyGroup.GroupBy( t => t.VehicleId );
foreach( IGrouping<String,Trip> vehicleGroup in groupedByVehicle )
{
String vehicleId = vehicleGroup.Key;
gfx.DrawString( "\tVehicle: " + vehicleId + "\r\n" );
foreach( Trip trip in vehicleGroup )
{
gfx.DrawString( $"\t\tTrip: {trip.Year}-{trip.Month:00}. {trip.PaymentNet,11:C2}\r\n" );
}
}
}
我添加了一些格式说明和字符,它们仅适用于文本模式(控制台应用程序),不适用于 PDF 渲染,但如果您好奇:
- 我使用制表符 (
\t
) 来指示缩进,以便对相关数据进行视觉分组。
- 我使用格式说明符
:00
来确保 Month
值显示为带前导零的 2 位数值。
- 我使用格式说明符
,11:C2
来确保 PaymentNet
值被格式化为带有 2 个小数位的货币值,并且始终左填充至至少 11 个字符宽度。
这会给你这样的输出(如下)。
请注意,虽然在您的源数据中每个 VehicleId
都只有一个与之关联的行程,但我上面的代码 允许 一个 VehicleId
以具有相同和不同 LicenseHolderId
值的多次行程,尽管下面的示例打印输出仅显示每辆车 1 次行程。
Company: CompanyName1
Vehicle: AG4203000002
Trip: 2021-07. 7,088.68
Vehicle: AG4203000003
Trip: 2021-07. 8,761.32
Company: CompanyName2:
Vehicle: AG4203000004
Trip: 2021-07. 9,264.15
Vehicle: AG4203000005
Trip: 2021-07. ,273.58
但请注意,上面的代码很糟糕,因为它 交叉了关注点 (它做了 2 件不同的事情:它遍历了一个非平凡的对象图,并将数据呈现给您的PDF 库)。
更好的设计会分离图形遍历(可能是单个扩展方法)从而使 PDF 渲染代码更简单,但是我不能给你任何代码示例在不了解更多关于您的数据库设计和 if/how 您正在使用 EF 的情况下了解这一点。
我正在使用 PDFsharp 创建发票。
这是我的 SQL table (tblTripsPerMonth
):
我已将其绑定到 ObservableCollection
(PaidTrips
)。
目标是为 LicenseHolderID
列中每个不同的“CompanyName”创建一 (1) 个 PDF。
为此,我转换为 List
,并按 LicenseHolderID
.
var paidTrips = PaidTrips
.GroupBy(p => new {
p.LicenseHolderID
})
.ToList();
之后,我用 foreach
循环遍历列表:
foreach (var trip in paidTrips) {
// I grab the distinct name
string licenseholder = trip.Key.LicenseHolderID.ToString();
// I summarize many of the columns
decimal totalPayment = trip.Sum(x => x.Payment);
decimal totalPaymentNet = trip.Sum(x => x.Payment);
decimal totalOrderFee = trip.Sum(x => x.Payment);
decimal totalPaymentFee = trip.Sum(x => x.Payment);
// I grab the first value of some other columns, which won't change
string licenseholderInvoiceID = trip.Select(x => x.LicenseHolderInvoiceID).FirstOrDefault().ToString();
string ridelRegionInvoiceID = trip.Select(x => x.RidelRegionInvoiceID ).FirstOrDefault().ToString();
// Creating PDF document using PDFsharp:
// PDFsharp code
// PDFsharp code
// PDFsharp code
}
我能够创建一个 PDF 文档,每个不同的 LicenseHolderID
,通过将 licenseHolderID
字符串添加到 PDFsharps document.Save()
的文件路径。
但是我无法用我需要的所有信息填写 PDF 文档。
我有汇总金额 - good,因为我绝对需要显示完整的发票金额。
但是——我还需要详细说明。我 没有 每个 VehicleID
的金额。
对于“CompanyName1”,将是 AG4203000002 和 AG4203000003,以及它们对应的行数据。
我确实这样做了...
IEnumerable<string> vehicleIds = trip
.Select(x => x.VehicleID)
.Distinct()
.ToArray();
string vehicle = string.Join(", ", vehicleIds);
...为了将 VehicleID
个不同的值彼此分开。
然后我将 string vehicle
放入 PDFsharp 中,将文本绘制到 PDF (DrawString
):
gfx.DrawString(vehicle, /* font and color customization */);
这为我提供了每个 LicenseHolderID
的正确数量的 VehicleID
,但在一个长字符串中...不是最优的。
这让我想到了我的问题: A):我需要携带与VehicleID
中的不同车辆,以便我可以在我的 PDF 中填写详细信息,而不仅仅是汇总值,以及 B):如果 的解决方案A) 涉及摆脱又长又难懂的字符串 (vehicle
),那将是最佳选择,如果不是 - 那也没关系。
更新(添加来自@Dai 的回答的代码):
// PaidTrip = My holder class, which I've bound to a ObservableCollection (PaidTrips)
var paidTrips = PaidTrips.ToList(); // I was unsure about this one
IEnumerable<IGrouping<String, PaidTrip>> tripsGroupedByCompany = paidTrips.GroupBy(pt => pt.LicenseHolderID);
foreach (IGrouping<String, PaidTrip>> companyGroup in tripsGroupedByCompany) {
string licenseHolderId = companyGroup.Key;
gfx.DrawString(/* code goes foo */);
// I tried adding Key here, but that gave me a squiggly under "t.VehicleID"
var groupedByVehicle = companyGroup.GroupBy(t => t.VehicleID);
foreach (IGrouping<String, PaidTrip> vehicleGroup in groupedByVehicle) {
// This is where I get a red squiggly; under Key
String vehicleId = groupedByVehicle.Key;
gfx.DrawString(/* code goes foo */);
foreach (PaidTrip trip in vehicleGroup) {
gfx.DrawString(/* code goes foo */);
}
}
}
这是错误:
CS1061: IEnumerable<IGrouping<string, PaidTrip>> does not contain a definition for 'Key' and no accessible extension method 'Key' accepting a first argument of type 'IEnumerable<IGrouping<string, PaidTrip>>' could be found (are you missing a using directive or an assembly reference?)
I need to bring along the row data of the other columns pertaining to the distinct vehicles in
VehicleId
, so that I can fill in details in my PDFs, and not just the summarized values.
如果我没理解错的话,对于每家公司 (LicenseHolderId
),您需要他们的相关 Trip
对象,但按 VehicleId
分组 - 这很简单,只需添加另一个 GroupBy
- 你可以在内部迭代它们 foreach
:
List<Trip> paidTrips = ...
IEnumerable< IGrouping<String,Trip> > tripsGroupedByCompany = paidTrips.GroupBy( pt => pt.LicenseHolderId );
foreach( IGrouping<String,Trip> companyGroup in tripsGroupedByCompany )
{
String licenseHolderId = companyGroup.Key;
gfx.DrawString( "Company: " + licenseHolderId + "\r\n" );
var groupedByVehicle = companyGroup.GroupBy( t => t.VehicleId );
foreach( IGrouping<String,Trip> vehicleGroup in groupedByVehicle )
{
String vehicleId = vehicleGroup.Key;
gfx.DrawString( "\tVehicle: " + vehicleId + "\r\n" );
foreach( Trip trip in vehicleGroup )
{
gfx.DrawString( $"\t\tTrip: {trip.Year}-{trip.Month:00}. {trip.PaymentNet,11:C2}\r\n" );
}
}
}
我添加了一些格式说明和字符,它们仅适用于文本模式(控制台应用程序),不适用于 PDF 渲染,但如果您好奇:
- 我使用制表符 (
\t
) 来指示缩进,以便对相关数据进行视觉分组。 - 我使用格式说明符
:00
来确保Month
值显示为带前导零的 2 位数值。 - 我使用格式说明符
,11:C2
来确保PaymentNet
值被格式化为带有 2 个小数位的货币值,并且始终左填充至至少 11 个字符宽度。
- 我使用制表符 (
这会给你这样的输出(如下)。
请注意,虽然在您的源数据中每个
VehicleId
都只有一个与之关联的行程,但我上面的代码 允许 一个VehicleId
以具有相同和不同LicenseHolderId
值的多次行程,尽管下面的示例打印输出仅显示每辆车 1 次行程。
Company: CompanyName1
Vehicle: AG4203000002
Trip: 2021-07. 7,088.68
Vehicle: AG4203000003
Trip: 2021-07. 8,761.32
Company: CompanyName2:
Vehicle: AG4203000004
Trip: 2021-07. 9,264.15
Vehicle: AG4203000005
Trip: 2021-07. ,273.58
但请注意,上面的代码很糟糕,因为它 交叉了关注点 (它做了 2 件不同的事情:它遍历了一个非平凡的对象图,并将数据呈现给您的PDF 库)。
更好的设计会分离图形遍历(可能是单个扩展方法)从而使 PDF 渲染代码更简单,但是我不能给你任何代码示例在不了解更多关于您的数据库设计和 if/how 您正在使用 EF 的情况下了解这一点。