unit U_CustomFun;

interface

uses
  System.SysUtils, System.Classes, Data.DB, System.Generics.Collections,
  System.StrUtils, Datasnap.DBClient;

type
  TProductTotals = class
  private
    FPieceCount: Integer;
    FQuantity: Double;
  public
    property PieceCount: Integer read FPieceCount write FPieceCount;
    property Quantity: Double read FQuantity write FQuantity;
    constructor Create;
  end;

  TProductNameTotalsDict = TDictionary<string, TProductTotals>;

function GetMergedResultsAsString(ClientDataSet: TClientDataSet): string;

function CustomSelCDSKey(CDS_1: TclientDataSet; Keys: TArray<string>): TArray<string>;

implementation

//uses
//  U_printPdf, U_RTFun, U_DataLink;

constructor TProductTotals.Create;
begin
  FPieceCount := 0;
  FQuantity := 0.0;
end;

function CustomSelCDSKey(CDS_1: TclientDataSet; Keys: TArray<string>): TArray<string>;
var
  RTValues: TArray<string>;
  i, j, CurRow: Integer;
begin
  SetLength(RTValues, Length(Keys));
  CurRow := CDS_1.recno;
  CDS_1.DisableControls;
  with CDS_1 do
  begin
    First;
    j := 0;
    while not Eof do
    begin
      if j = 0 then
      begin
        for i := 0 to Length(RTValues) - 1 do
        begin
          RTValues[i] := Trim(CDS_1.fieldbyname(Keys[i]).AsString) + ',';
        end;
      end
      else
      begin
        for i := 0 to Length(RTValues) - 1 do
        begin
          RTValues[i] := RTValues[i] + Trim(CDS_1.fieldbyname(Keys[i]).AsString) + ',';
        end;
      end;
      j := j + 1;

      CDS_1.Next;
    end;
  end;
  CDS_1.recno := CurRow;
  CDS_1.EnableControls;

  for i := 0 to Length(RTValues) - 1 do
  begin
    RTValues[i] := copy(RTValues[i], 1, Length(RTValues[i]) - 1);
  end;

  Result := RTValues;
end;

function GetMergedResultsAsString(ClientDataSet: TClientDataSet): string;
var
  ProductNameTotalsDict: TProductNameTotalsDict;
  ProductName: string;
  PieceCount: Integer;
  Quantity: Double;
  ProductNameList: TStringList;
  ProductTotals: TProductTotals;
  I: Integer;
begin
  ProductNameTotalsDict := TProductNameTotalsDict.Create;
  try
    ClientDataSet.IndexName := ''; // 清空索引
    ClientDataSet.First;

    while not ClientDataSet.Eof do
    begin
      ProductName := ClientDataSet.FieldByName('Grade').AsString;
      PieceCount := ClientDataSet.FieldByName('Piece').AsInteger;
      Quantity := ClientDataSet.FieldByName('Qty').AsFloat;

      if not ProductNameTotalsDict.ContainsKey(ProductName) then
      begin
        ProductTotals := TProductTotals.Create;
        ProductTotals.PieceCount := PieceCount;
        ProductTotals.Quantity := Quantity;
        ProductNameTotalsDict.Add(ProductName, ProductTotals);
      end
      else
      begin
        ProductTotals := ProductNameTotalsDict[ProductName];
        ProductTotals.PieceCount := ProductTotals.PieceCount + PieceCount;
        ProductTotals.Quantity := ProductTotals.Quantity + Quantity;
      end;

      ClientDataSet.Next;
    end;

    ProductNameList := TStringList.Create;
    try
      for ProductName in ProductNameTotalsDict.Keys do
      begin
        ProductTotals := ProductNameTotalsDict[ProductName];
        ProductNameList.Add(Format('%s: 支数=%d, 数量=%.2f', [ProductName, ProductTotals.PieceCount, ProductTotals.Quantity]));
      end;

      ProductNameList.Sort;
      Result := StringReplace(ProductNameList.Text, #13#10, '; ', [rfReplaceAll]);
    finally
      ProductNameList.Free;

      // 清理字典中的对象，避免内存泄漏
      for ProductTotals in ProductNameTotalsDict.Values do
      begin
        ProductTotals.Free;
      end;
      ProductNameTotalsDict.Clear;
    end;
  finally
    ProductNameTotalsDict.Free;
  end;
end;

end.

