英文:
Displaying Sub Totals based on Dates in DataRow of DataTable using Flutter
问题
我想实现如下的 DataTable,它在每个唯一日期后显示小计,包含对象数组。
以下是我用于根据唯一日期对数组进行排序的代码:
class _DateWiseReportState extends State<DateWiseReport> {
List<Map> _reports = [
{
'scan_date': '01.07.23',
'engine_type': '2S',
'coupon_value': 5,
'quantity': 3,
'amount': 15,
},
{
'scan_date': '01.07.23',
'engine_type': '4S',
'coupon_value': 10,
'quantity': 2,
'amount': 20,
},
{
'scan_date': '01.07.23',
'engine_type': '3W',
'coupon_value': 10,
'quantity': 2,
'amount': 20,
},
{
'scan_date': '02.07.23',
'engine_type': '2S',
'coupon_value': 5,
'quantity': 2,
'amount': 10,
},
{
'scan_date': '02.07.23',
'engine_type': '4S',
'coupon_value': 10,
'quantity': 3,
'amount': 30,
},
{
'scan_date': '01.07.23',
'engine_type': '3W',
'coupon_value': 10,
'quantity': 3,
'amount': 30,
}
];
// 在这里添加计算小计的代码
_reports.sort((a, b) {
return a['scan_date'].compareTo(b['scan_date']!);
});
// 在这里添加创建列的代码
// 在这里添加创建行的代码
}
请添加计算小计、创建列和创建行的代码,以实现所需的输出效果。
英文:
I want to achieve the DataTable like below that displays sub totals after each unique dates having array of objects
Below is the code which I used to sort the array based on unique dates
class _DateWiseReportState extends State<DateWiseReport> {
List<Map> _reports = [
{
'scan_date': '01.07.23',
'engine_type': '2S',
'coupon_value': 5,
'quantity': 3,
'amount': 15,
},
{
'scan_date': '01.07.23',
'engine_type': '4S',
'coupon_value': 10,
'quantity': 2,
'amount': 20,
},
{
'scan_date': '01.07.23',
'engine_type': '3W',
'coupon_value': 10,
'quantity': 2,
'amount': 20,
},
{
'scan_date': '02.07.23',
'engine_type': '2S',
'coupon_value': 5,
'quantity': 2,
'amount': 10,
},
{
'scan_date': '02.07.23',
'engine_type': '4S',
'coupon_value': 10,
'quantity': 3,
'amount': 30,
},
{
'scan_date': '01.07.23',
'engine_type': '3W',
'coupon_value': 10,
'quantity': 3,
'amount': 30,
}
];
for (var reportData in _reports) {
int quantity = reportData['quantity'];
int amount = reportData['amount'];
int couponValue = reportData['coupon_value'];
totalQuantity += quantity.toInt();
totalAmount += amount.toInt();
totalCouponValue += couponValue.toInt();
}
_reports.sort((a, b) {
return a['scan_date'].compareTo(b['scan_date']!);
});
List<DataColumn> _createColumns() {
return [
DataColumn(
label: Expanded(
child: Text(
'Scan Date',
textAlign: TextAlign.center,
))),
DataColumn(
label: Text(
'E-Type',
textAlign: TextAlign.center,
)),
DataColumn(
label: Expanded(
child: Text(
'Value',
textAlign: TextAlign.center,
))),
DataColumn(
label: Expanded(
child: Text(
'QTY',
textAlign: TextAlign.center,
))),
DataColumn(
label: Expanded(
child: Text(
'Amount(Rs)',
textAlign: TextAlign.center,
)),
onSort: (columnIndex, _) {
setState(() {
_currentSortColumn = columnIndex;
if (_isSortAsc) {
_reports.sort((a, b) => b['amount'].compareTo(a['amount']));
} else {
_reports.sort((a, b) => a['amount'].compareTo(b['amount']));
}
_isSortAsc = !_isSortAsc;
});
},
),
];
}
List<DataRow> _createRows() {
return _reports
.map((report) => DataRow(cells: [
DataCell(
Text(
report['scan_date'].toString(),
textAlign: TextAlign.center,
), onTap: () {
print("Clicked row at scan_date");
}),
DataCell(
Text(
report['engine_type'].toString(),
textAlign: TextAlign.center,
), onTap: () {
print("Clicked row at engine_type");
}),
DataCell(
Text(
report['coupon_value'].toString(),
textAlign: TextAlign.center,
), onTap: () {
print("Clicked row at coupon_value");
}),
DataCell(
Text(
report['quantity'].toString(),
textAlign: TextAlign.center,
), onTap: () {
print("Clicked row at quantity");
}),
DataCell(
Text(
report['amount'].toString(),
textAlign: TextAlign.center,
), onTap: () {
print("Clicked row at amount");
})
]))
.toList();
}
Can anyone suggest how we can achieve the sub totals based on after unique dates.
答案1
得分: 2
以下是您要翻译的代码部分:
List<DataRow> _createRows() {
List<DataRow> rows = [];
int currentSubtotalAmount = 0;
// Flag for first iteration otherwise it will add subtotal row at the beginning
bool isFirstIteration = true;
_reports.sort((a, b) {
final aDate = a['scan_date'] as String;
final bDate = b['scan_date'] as String;
return aDate.compareTo(bDate);
});
for (var report in _reports) {
final reportDate = report['scan_date'] as String;
if (reportDate != currentDate) {
// Add a subtotal row for the previous date group
if (currentDate.isNotEmpty && currentSubtotalAmount > 0) {
rows.add(_createSubtotalRow(currentSubtotalAmount));
currentSubtotalAmount = 0;
}
currentDate = reportDate;
// Only add date row if it's not the first iteration
if (!isFirstIteration) {
rows.add(_createDateRow(currentDate));
}
}
rows.add(_createReportRow(report));
currentSubtotalAmount += report['amount'] as int;
// After first iteration, set the flag to false
if (isFirstIteration) {
isFirstIteration = false;
}
}
// Add a final subtotal row
rows.add(_createSubtotalRow(currentSubtotalAmount));
return rows;
}
如果您需要翻译其他部分,请告诉我。
英文:
Result
Explanation
I've refactored your code and created a _createRows
function where the main logic is:
List<DataRow> _createRows() {
List<DataRow> rows = [];
int currentSubtotalAmount = 0;
// Flag for first iteration otherwise it will add subtotal row at the beginning
bool isFirstIteration = true;
_reports.sort((a, b) {
final aDate = a['scan_date'] as String;
final bDate = b['scan_date'] as String;
return aDate.compareTo(bDate);
});
for (var report in _reports) {
final reportDate = report['scan_date'] as String;
if (reportDate != currentDate) {
// Add a subtotal row for the previous date group
if (currentDate.isNotEmpty && currentSubtotalAmount > 0) {
rows.add(_createSubtotalRow(currentSubtotalAmount));
currentSubtotalAmount = 0;
}
currentDate = reportDate;
// Only add date row if it's not the first iteration
if (!isFirstIteration) {
rows.add(_createDateRow(currentDate));
}
}
rows.add(_createReportRow(report));
currentSubtotalAmount += report['amount'] as int;
// After first iteration, set the flag to false
if (isFirstIteration) {
isFirstIteration = false;
}
}
// Add a final subtotal row
rows.add(_createSubtotalRow(currentSubtotalAmount));
return rows;
}
The loop iterates through each report in the _reports
list:
If the current report's 'scan_date'
is different from the currentDate
, it means a new date group has started. And in that case:
-
If currentDate is not empty (Meaning, not the first date
encountered), it adds a subtotal row for the previous date
group using_createSubtotalRow(currentSubtotalAmount)
. -
It resets currentSubtotalAmount to 0 because a new date group has started
Code
import 'package:flutter/material.dart';
void main() async {
runApp(ExampleWidget());
}
class ExampleWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: DateWiseReport(),
);
}
}
class DateWiseReport extends StatefulWidget {
const DateWiseReport({Key? key}) : super(key: key);
@override
State<DateWiseReport> createState() => _DateWiseReportState();
}
class _DateWiseReportState extends State<DateWiseReport> {
final _reports = [
{
'scan_date': '01.07.23',
'engine_type': '2S',
'coupon_value': 5,
'quantity': 3,
'amount': 15,
},
{
'scan_date': '01.07.23',
'engine_type': '4S',
'coupon_value': 10,
'quantity': 2,
'amount': 20,
},
{
'scan_date': '01.07.23',
'engine_type': '3W',
'coupon_value': 10,
'quantity': 2,
'amount': 20,
},
{
'scan_date': '02.07.23',
'engine_type': '2S',
'coupon_value': 5,
'quantity': 2,
'amount': 10,
},
{
'scan_date': '02.07.23',
'engine_type': '4S',
'coupon_value': 10,
'quantity': 3,
'amount': 30,
},
{
'scan_date': '01.07.23',
'engine_type': '3W',
'coupon_value': 10,
'quantity': 3,
'amount': 30,
}
];
late String currentDate = _reports[0]['scan_date'] as String;
void _sortReportsByAmount() {
_reports.sort((a, b) {
final aAmount = a['amount'] as int;
final bAmount = b['amount'] as int;
return aAmount.compareTo(bAmount);
});
}
List<DataColumn> _createColumns() {
return [
DataColumn(label: Text('Scan Date', textAlign: TextAlign.center)),
DataColumn(label: Text('E-Type', textAlign: TextAlign.center)),
DataColumn(label: Text('Value', textAlign: TextAlign.center)),
DataColumn(label: Text('QTY', textAlign: TextAlign.center)),
DataColumn(
label: Text('Amount(Rs)', textAlign: TextAlign.center),
onSort: (columnIndex, _) {
setState(() {
_sortReportsByAmount();
});
},
),
];
}
List<DataRow> _createRows() {
List<DataRow> rows = [];
int currentSubtotalAmount = 0;
// Flag for first iteration otherwise it will add subtotal row at the beginning
bool isFirstIteration = true;
_reports.sort((a, b) {
final aDate = a['scan_date'] as String;
final bDate = b['scan_date'] as String;
return aDate.compareTo(bDate);
});
for (var report in _reports) {
final reportDate = report['scan_date'] as String;
if (reportDate != currentDate) {
// Add a subtotal row for the previous date group
if (currentDate.isNotEmpty && currentSubtotalAmount > 0) {
rows.add(_createSubtotalRow(currentSubtotalAmount));
currentSubtotalAmount = 0;
}
currentDate = reportDate;
// Only add date row if it's not the first iteration
if (!isFirstIteration) {
rows.add(_createDateRow(currentDate));
}
}
rows.add(_createReportRow(report));
currentSubtotalAmount += report['amount'] as int;
// After first iteration, set the flag to false
if (isFirstIteration) {
isFirstIteration = false;
}
}
// Add a final subtotal row
rows.add(_createSubtotalRow(currentSubtotalAmount));
return rows;
}
DataRow _createDateRow(String date) {
return DataRow(cells: [
DataCell(Text(date, textAlign: TextAlign.center)),
DataCell(Text(''), // Empty cell for E-Type
onTap: () {
print("Clicked date cell");
}),
DataCell(Text(''), // Empty cell for Value
onTap: () {
print("Clicked date cell");
}),
DataCell(Text(''), // Empty cell for QTY
onTap: () {
print("Clicked date cell");
}),
DataCell(Text(''), // Empty cell for Amount
onTap: () {
print("Clicked date cell");
}),
]);
}
DataRow _createReportRow(Map<String, dynamic> report) {
return DataRow(cells: [
DataCell(
Text(report['scan_date'].toString(), textAlign: TextAlign.center),
onTap: () {
print("Clicked row at scan_date");
}),
DataCell(
Text(report['engine_type'].toString(), textAlign: TextAlign.center),
onTap: () {
print("Clicked row at engine_type");
}),
DataCell(
Text(report['coupon_value'].toString(), textAlign: TextAlign.center),
onTap: () {
print("Clicked row at coupon_value");
}),
DataCell(Text(report['quantity'].toString(), textAlign: TextAlign.center),
onTap: () {
print("Clicked row at quantity");
}),
DataCell(Text(report['amount'].toString(), textAlign: TextAlign.center),
onTap: () {
print("Clicked row at amount");
}),
]);
}
DataRow _createSubtotalRow(int subtotalAmount) {
return DataRow(
cells: [
DataCell(Text(
'Subtotal',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
)),
DataCell(Text(''), // Empty cell for E-Type
onTap: () {
print("Clicked subtotal cell");
}),
DataCell(Text(''), // Empty cell for Value
onTap: () {
print("Clicked subtotal cell");
}),
DataCell(Text(''), // Empty cell for QTY
onTap: () {
print("Clicked subtotal cell");
}),
DataCell(
Text(subtotalAmount.toString(),
textAlign: TextAlign.center,
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
onTap: () {
print("Clicked subtotal cell");
}),
],
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Date Wise Report'),
),
body: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: DataTable(
columns: _createColumns(),
rows: _createRows(),
),
),
);
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论