在一個項目中,使用DBGrideh,當使用自帶的內存數據集時,對於Footers添加的求平均值,一直顯示為0,其他匯總數據都是可以的,而切換使用TClientDataSet或者TADODataSet,所有匯總數據包括平均值都有值。
打開相關部分源碼查看了下,發現DBGrideh自帶的內存數據集關於匯總平均數這塊,竟然沒有處理……,什麼情況?
原始相關函數:
procedure TCustomMemTableEh.GetAggregatedValuesForRange(FromBM, ToBM: TUniBookmarkEh; FieldName: String; var ResultArr: TAggrResultArr; AggrFuncs: TAggrFunctionsEh); var FromRN, ToRN: Integer; i: Integer; v: Variant; VarTypeNum: Integer; FieldIndex: Integer; begin ResultArr[agfSumEh] := Null; ResultArr[agfCountEh] := 0; ResultArr[agfAvg] := Null; ResultArr[agfMin] := Null; ResultArr[agfMax] := Null; if not Active then Exit; if FromBM <> NilBookmarkEh then if UniBookmarkValid(FromBM) then FromRN := UniBookmarkToRecNo(FromBM) else Exit else FromRN := 1; if ToBM <> NilBookmarkEh then if UniBookmarkValid(ToBM) then ToRN := UniBookmarkToRecNo(ToBM) else Exit else ToRN := RecordCount; if (FieldName = '') and (AggrFuncs = [agfCountEh]) then begin for i := FromRN-1 to ToRN-1 do ResultArr[agfCountEh] := ResultArr[agfCountEh] + 1; Exit; end; if FRecordsView.MemTableData.DataStruct.FindField(FieldName) = nil then Exit; VarTypeNum := FRecordsView.MemTableData.DataStruct.FieldByName(FieldName).GetVarDataType; FieldIndex := FRecordsView.MemTableData.DataStruct.FieldIndex(FieldName); for i := FromRN-1 to ToRN-1 do begin v := FRecordsView.RecordView[i].Rec.Value[FieldIndex, dvvValueEh]; if not VarIsNullEh(v) then begin if (agfCountEh in AggrFuncs) or (agfAvg in AggrFuncs) then ResultArr[agfCountEh] := ResultArr[agfCountEh] + 1; //當設置求平均值時,此處僅僅做了一次記數累計 if (VarTypeNum in [varSmallint, varInteger, varSingle, varDouble, varCurrency, {$IFDEF EH_LIB_6} varShortInt, varWord, varInt64, varLongWord, {$ENDIF} varByte, varDate]) or (VarTypeNum = varFMTBcd) then begin if (agfSumEh in AggrFuncs) and (VarTypeNum <> varDate) then if VarIsNullEh(ResultArr[agfSumEh]) then ResultArr[agfSumEh] := v else ResultArr[agfSumEh] := ResultArr[agfSumEh] + v; if agfMin in AggrFuncs then if VarIsNullEh(ResultArr[agfMin]) then ResultArr[agfMin] := v else if ResultArr[agfMin] > v then ResultArr[agfMin] := v; if agfMax in AggrFuncs then if VarIsNullEh(ResultArr[agfMax]) then ResultArr[agfMax] := v else if ResultArr[agfMax] < v then ResultArr[agfMax] := v; end end; end; if agfMax in AggrFuncs then //求平均值,此處的觸發條件竟然是 agfMax .... if not VarIsNullEh(ResultArr[agfSumEh]) then ResultArr[agfAvg] := ResultArr[agfSumEh] / ResultArr[agfCountEh]; //此處因為沒有在agfAvg時對agfSumEh 求和匯總,該值應為0; end;
修改方法:
1、打開MemTableEh.pas
2、找到GetAggregatedValuesForRange函數,修改成如下:
procedure TCustomMemTableEh.GetAggregatedValuesForRange(FromBM, ToBM: TUniBookmarkEh; FieldName: String; var ResultArr: TAggrResultArr; AggrFuncs: TAggrFunctionsEh); var FromRN, ToRN: Integer; i: Integer; v: Variant; VarTypeNum: Integer; FieldIndex: Integer; begin ResultArr[agfSumEh] := Null; ResultArr[agfCountEh] := 0; ResultArr[agfAvg] := Null; ResultArr[agfMin] := Null; ResultArr[agfMax] := Null; if not Active then Exit; if FromBM <> NilBookmarkEh then if UniBookmarkValid(FromBM) then FromRN := UniBookmarkToRecNo(FromBM) else Exit else FromRN := 1; if ToBM <> NilBookmarkEh then if UniBookmarkValid(ToBM) then ToRN := UniBookmarkToRecNo(ToBM) else Exit else ToRN := RecordCount; if (FieldName = '') and (AggrFuncs = [agfCountEh]) then begin for i := FromRN-1 to ToRN-1 do ResultArr[agfCountEh] := ResultArr[agfCountEh] + 1; Exit; end; if FRecordsView.MemTableData.DataStruct.FindField(FieldName) = nil then Exit; VarTypeNum := FRecordsView.MemTableData.DataStruct.FieldByName(FieldName).GetVarDataType; FieldIndex := FRecordsView.MemTableData.DataStruct.FieldIndex(FieldName); for i := FromRN-1 to ToRN-1 do begin v := FRecordsView.RecordView[i].Rec.Value[FieldIndex, dvvValueEh]; if not VarIsNullEh(v) then begin if (agfCountEh in AggrFuncs) or (agfAvg in AggrFuncs) then ResultArr[agfCountEh] := ResultArr[agfCountEh] + 1; if (VarTypeNum in [varSmallint, varInteger, varSingle, varDouble, varCurrency, {$IFDEF EH_LIB_6} varShortInt, varWord, varInt64, varLongWord, {$ENDIF} varByte, varDate]) or (VarTypeNum = varFMTBcd) then begin if ((agfSumEh in AggrFuncs) or (agfAvg in AggrFuncs)) and (VarTypeNum <> varDate) then //此處修改 if VarIsNullEh(ResultArr[agfSumEh]) then ResultArr[agfSumEh] := v else ResultArr[agfSumEh] := ResultArr[agfSumEh] + v; if agfMin in AggrFuncs then if VarIsNullEh(ResultArr[agfMin]) then ResultArr[agfMin] := v else if ResultArr[agfMin] > v then ResultArr[agfMin] := v; if agfMax in AggrFuncs then if VarIsNullEh(ResultArr[agfMax]) then ResultArr[agfMax] := v else if ResultArr[agfMax] < v then ResultArr[agfMax] := v; end end; end; if agfAvg in AggrFuncs then //此處修改 if not VarIsNullEh(ResultArr[agfSumEh]) then ResultArr[agfAvg] := ResultArr[agfSumEh] / ResultArr[agfCountEh]; end;