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; function GetMergedResultsAsString(ClientDataSet: TClientDataSet): string; function CustomSelCDSKey(CDS_1: TclientDataSet; Keys: TArray): TArray; 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): TArray; var RTValues: TArray; 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.