// 调用示例:函数 CalcExpression(M_DataSet,D_DataSet:TDataSet;Source:String)
ouble;<br>// CalcStr=基本工资+项目工资*2-if(请假天数>5,100,if(请假天数=0,-50,50))<br>// CalcExpression(DataSet,nil,CalcStr)<br>// {数据字段可以为中文或英文,要求字段均为数值类型}<br>unit CalcExpress;<br>interface<br>Uses Windows, Messages,SysUtils,Variants,Classes,DB;<br> //----------------------------- 共用变量 ---------------------------<br> //------ 通用函数 -----------------------------<br> Function IsNumber(Source:String):Boolean;<br> Function IIF(B:Boolean;V1,V2:Integer):Integer;Overload;<br> Function IIF(B:Boolean;V1,V2
ouble)
ouble;Overload;<br> Function IIF(B:Boolean;V1,V2:String):String;Overload;<br> Function BigMoney(FormatStr:String;Value
ouble):String;<br> //--------------------------------------------- <br> Function CalcExpression(M_DataSet,D_DataSet:TDataSet;Source:String)
ouble;<br> Function MainCalc(Source:String)
ouble;<br> Function SubCalcAdd(Source:String)
ouble; // 用来计算加减法<br> Function SubCalcMult(Source:String)
ouble; // 用来计算乘除法<br> //--------------------------------------------- <br> Function GetFieldName(CurDataSet:TDataSet;Source:String):String;<br> Function GetFieldValue(Source:String)
ouble;<br> Function GetFieldValueAsString(CurDataSet:TDataSet;Source:String):String;<br> Function GetFieldValueAsInteger(CurDataSet:TDataSet;Source:String):Integer;<br> Function GetFieldValueAsDouble(CurDataSet:TDataSet;Source:String)
ouble;<br> Function FuncAnalyzer(Source:String;iLPos,iRPos:Integer):String;<br> Function IF_Analyzer(Source:String;iLPos,iRPos:Integer):String; // IF 分析单元<br> function SSWR(s: real):real;<br>Var<br> MainDataSet,DetailDataSet:TDataSet;<br> <br>implementation<br>Function IsNumber(Source:String):Boolean;<br>Var I,J,iCount:Integer;<br> Value:Byte;<br>begin<br> Result:=True;<br> J:=0; <br> Source:=Trim(Source); <br> iCount:=Length(Source); <br> For I:=1 to iCount do <br> begin <br> Value:=Ord(Source
); <br> if Value=Ord('.') then <br> begin <br> J:=J+1; <br> if (J>=2) or (I=1) or (I=iCount) then begin <br> Result:=False; <br> Exit; <br> end; <br> Continue; <br> end; <br> if (Value<Ord('0')) or (Value>Ord('9')) then begin <br> Result:=False; <br> Exit ; <br> end; <br> end; <br> end; <br> <br>Function IIF(B:Boolean;V1,V2:Integer):Integer;Overload;<br> begin <br> if B then Result:=V1 else Result:=V2; <br> end; <br> <br>Function IIF(B:Boolean;V1,V2ouble)ouble;Overload;<br> begin <br> if B then Result:=V1 else Result:=V2; <br> end; <br> <br>Function IIF(B:Boolean;V1,V2:String):String;Overload;<br>begin<br> if B then Result:=V1 else Result:=V2; <br>end;<br> <br>Function BigMoney(FormatStr:String;Valueouble):String;<br> var SmallMoney,BigMoney:string;<br> C,C1,FrontStr,BackStr:string; <br> I,DotPos,CurPos,P1,P2:Integer; <br> begin <br> Result:=''; <br> CurPos:=0; <br> if FormatStr='' then <br> FormatStr:='0.00' <br> else begin <br> For I:=1 to Length(FormatStr) do <br> begin <br> if FormatStr='0' then begin <br> P1:=I; <br> Break; <br> end; <br> end; <br> For I:=Length(FormatStr) downto 1 do <br> begin <br> if FormatStr='0' then begin <br> P2:=I; <br> Break; <br> end; <br> end; <br> FrontStr:=Copy(FormatStr,1,P1-1); <br> BackStr:=Copy(FormatStr,P2+1,Length(FormatStr)); <br> FormatStr:=Copy(FormatStr,P1,P2-P1+1); <br> end; <br> SmallMoney:=Formatfloat(FormatStr,Value); <br> DotPos:=Pos('.',SmallMoney);{小数点的位置} <br> For I:=Length(SmallMoney) downto 1 do <br> begin <br> if I=DotPos then <br> Continue <br> else if I>DotPos then <br> CurPos:=DotPos-I <br> else if I<DotPos then <br> CurPos:=DotPos-I-1; <br> //-------------------------------------- <br> case StrToInt(SmallMoney) of <br> 1:C:='壹'; 2:C:='贰'; <br> 3:C:='叁'; 4:C:='肆'; <br> 5:C:='伍'; 6:C:='陆'; <br> 7:C:='柒'; 8:C:='捌'; <br> 9:C:='玖'; 0:C:='零'; <br> end; <br> case CurPos of <br> -4:C1:='毫'; <br> -3:C1:='厘'; <br> -2:C1:='分'; <br> -1:C1:='角'; <br> 0 :C1:='元'; <br> 1 :C1:='拾'; <br> 2 :C1:='佰'; <br> 3 :C1:='千'; <br> 4 :C1:='万'; <br> 5 :C1:='拾'; <br> 6 :C1:='佰'; <br> 7 :C1:='千';<br> 8 :C1:='亿'; <br> 9 :C1:='十'; <br> 10:C1:='佰'; <br> 11:C1:='千'; <br> 12:C1:='万'; <br> else <br> C1:='X'; <br> C:='X'; <br> end; <br> Result:=C+C1+Result; <br> end; <br> Result:=FrontStr+Result+BackStr; <br> end; <br><br>Function CalcExpression(M_DataSet,D_DataSet:TDataSet;Source:String)ouble;<br> Var I,iCount:Integer; <br> C : Char ; <br> TmpStr : String ; <br> begin <br> MainDataSet:=M_DataSet; <br> DetailDataSet:=D_DataSet; <br> iCount:=Length(Source); <br> For I:=1 to iCount Do <br> begin <br> C:=Source; <br> if C<>' ' then TmpStr:=TmpStr+C <br> End; <br> //------------------------------------ <br> Result:=MainCalc(TmpStr) <br> end; <br> <br>Function MainCalc(Source:String)ouble;<br>Var TmpStr:String;<br> C:Char; <br> I,iLeft,iRight,iLeftPos,iRightPos,iCount:Integer; <br> Label FirstRow; <br> begin <br> Result:=0; <br> FirstRow: <br> if IsNumber(Source) then begin <br> Result:=StrToFloat(Source); <br> Exit; <br> end; <br> //---------initting Data---------------------- <br> iLeft:=0;iRight:=0;iLeftPos:=0;iRightPos:=0; <br> TmpStr:=''; <br> //-------------------------------------------- <br> iCount:=Length(Source); <br> For I:=1 to iCount do begin <br> C:=Source; <br> if C='(' then begin <br> Inc(iLeft); <br> if iLeft=1 then iLeftPos:=I <br> end else if C=')' then begin <br> Inc(iRight); <br> if iRight=iLeft then iRightPos:=I <br> end; <br> if (iLeft=iRight) and (iLeft>0) then Break; <br> End; <br> if iLeft=0 then begin <br> Result:=SubCalcAdd(Source); <br> Exit; <br> end; <br> //---------------------------------------------- <br> Source:=FuncAnalyzer(Source,iLeftPos,iRightPos); <br> Goto FirstRow; <br> end; <br> <br>Function SubCalcAdd(Source:String)ouble;<br>Var I,J,iPos,iCount :Integer;<br> S :Array of String; <br> C,TmpStr:String; <br> iTotalouble; <br>begin<br> J:=0 ; <br> iPos:=1 ; <br> iTotal:=0; <br> iCount:=Length(Source); <br> S:=Nil; <br> //------------------------------------------- <br> For I:=1 to iCount do begin <br> C:=Source; <br> if (I=1) and (C='-') then Continue; <br> if (C='+') or (C='-') then begin <br> J:=J+1; <br> SetLength(S,J); <br> S[J-1]:=Copy(Source,iPos,I -iPos); <br> J:=J+1; <br> SetLength(S,J); <br> S[J-1]:=Copy(Source,I,1); <br> iPos:=I+1; <br> end <br> end; <br> J:=J+1; <br> SetLength(S,J); <br> S[J-1]:=Copy(Source,iPos,(I -iPos+1)); <br> //For I:=Low(S) to High(S) do TmpStr:=TmpStr+S; <br> //ShowMessage(TmpStr); <br> //------------------------------------------- <br> For I:=Low(S) to High(S) do begin <br> TmpStr:=S; <br> if I=0 then <br> iTotal:=SubCalcMult(TmpStr) <br> else <br> if (I-1)/2=(I-1) div 2 then <br> if TmpStr='+' then <br> iTotal:=iTotal + SubCalcMult(S[I+1]) <br> else <br> iTotal:=iTotal - SubCalcMult(S[I+1]) <br> else <br> Continue; <br> end; <br> //------------------------------------------- <br> //ShowMessage(FloatToStr(iTotal)); <br> Result:=iTotal ; <br> end; <br> <br>Function SubCalcMult(Source:String)ouble;<br>Var I,J,iCount,iPos:Integer;<br> iTotalouble; <br> C:Char; <br> TmpStr:String; <br> S:Array of String; <br>begin<br> if IsNumber(Source) then <br> begin <br> Result:=StrToFloat(Source); <br> Exit; <br> end; <br> iCount:=Length(Source); <br> J:=0; iTotal:=0; iPos:=1; <br> For I:=1 to iCount do begin <br> C:=Source; <br> if (C='*') or (C='/') then begin <br> J:=J+1 ; <br> SetLength(S,J); <br> S[J-1]:=Copy(Source,iPos,I -iPos); <br> J:=J+1 ; <br> SetLength(S,J); <br> S[J-1]:=Copy(Source,I,1); <br> iPos:=I+1; <br> end ; <br> End; <br> J:=J+1; <br> SetLength(S,J); <br> S[J-1]:=Copy(Source,iPos,(I -iPos+1)); <br> //---------------------------------------- <br> for I:=Low(S) to High(S) do begin <br> TmpStr:=S; <br> if I=0 then <br> if IsNumber(TmpStr) then <br> iTotal:=StrToFloat(TmpStr) <br> else <br> iTotal:=GetFieldValue(TmpStr) <br> else begin <br> if (I-1)/2=(I-1) div 2 then <br> if TmpStr='*' then begin <br> TmpStr:=S[I+1]; <br> if IsNumber(TmpStr) then <br> iTotal:=StrToFloat(TmpStr)*iTotal <br> else <br> iTotal:=GetFieldValue(TmpStr)*iTotal; <br> end else begin <br> TmpStr:=S[I+1]; <br> if IsNumber(TmpStr) then <br> iTotal:=iTotal/StrToFloat(TmpStr) <br> else <br> iTotal:=iTotal/GetFieldValue(TmpStr) <br> end <br> else <br> Continue <br> end; <br> end; <br> //---------------------------------- <br> Result:=iTotal ; <br> end;<br><br>Function GetFieldName(CurDataSet:TDataSet;Source:String):String;<br> Var I,J:Integer; <br> begin <br> Result:=''; <br> For I:=0 to CurDataSet.FieldCount-1 do <br> begin <br> if (CurDataSet.Fields.DisplayLabel=Source) or <br> (UpperCase(CurDataSet.Fields.FieldName)= <br> UpperCase(Source)) then <br> begin <br> Result:=CurDataSet.Fields.FieldName; <br> Exit; <br> end; <br> end; <br> end; <br>Function GetFieldValue(Source:String)ouble;<br> Var I,X,Y:Integer; //如果给了@ 就表示是标准格式,否者就是从表字段; <br> Label NextSet; <br> begin <br> //-------------------------------------------- <br> if DetailDataSet=nil then Goto NextSet; <br> for I:=0 to DetailDataSet.FieldCount-1 do <br> begin <br> if (DetailDataSet.Fields.DisplayLabel=Source) or <br> (UpperCase(DetailDataSet.Fields.FieldName)= <br> UpperCase(Source)) then <br> begin <br> Result:=DetailDataSet.Fields.AsFloat; <br> Exit; <br> end; <br> end; <br> <br> NextSet: <br> for I:=0 to MainDataSet.FieldCount-1 do <br> begin <br> if (MainDataSet.Fields.DisplayLabel=Source) or <br> (UpperCase(MainDataSet.Fields.FieldName)=UpperCase(Source)) then <br> begin <br> Result:=MainDataSet.Fields.AsFloat; <br> Exit; <br> end; <br> end;<br> Abort; <br> end; <br>Function GetFieldValueAsString(CurDataSet:TDataSet;Source:String):String;<br> Var cFieldName:String; <br> begin <br> cFieldName:=GetFieldName(CurDataSet,Source); <br> Result:=CurDataSet.FieldByName(cFieldName).AsString; <br> end; <br> <br> Function GetFieldValueAsInteger(CurDataSet:TDataSet;Source:String):Integer; <br> Var cFieldName:String; <br> begin <br> cFieldName:=GetFieldName(CurDataSet,Source); <br> Result:=CurDataSet.FieldByName(cFieldName).AsInteger; <br> end; <br>Function GetFieldValueAsDouble(CurDataSet:TDataSet;Source:String)ouble;<br> Var cFieldName:String; <br> begin <br> cFieldName:=GetFieldName(CurDataSet,Source);<br> Result:=CurDataSet.FieldByName(cFieldName).AsFloat;<br> end; <br>Function FuncAnalyzer(Source:String;iLPos,iRPos:Integer):String;<br> Var I,iCount:Integer; <br> TmpStr:String; <br> begin <br> iCount:=Length(Source); <br> if (iLPos>=2) and (LowerCase(Copy(Source,iLPos -2,2))='if') then <br> TmpStr:=IF_Analyzer(Source,iLPos,iRPos) <br> //MessageBox('uf_Analyze_if',TmpStr) <br> else if (iLPos>=6) and (LowerCase(Copy(Source,iLPos -2,2))='isnull') then <br> //TmpStr=String(uf_Analyze_IsNull(Source)) <br> else if (iLPos>=4) and (LowerCase(Copy(Source,iLPos -2,2))='left') then <br> //TmpStr=uf_Analyze_IsNull(Source) <br> else begin <br> TmpStr:=Copy(Source,1,(iLPos -1)); <br> TmpStr:=TmpStr+FloatToStr(MainCalc(Copy(Source, <br> iLPos+1,(iRPos -iLPos -1)))); <br> TmpStr:=TmpStr+Copy(Source,iRPos+1,(iCount -iRPos)); <br> <br> end ; <br> <br> Result:=TmpStr <br> end;<br>Function IF_Analyzer(Source:String;iLPos,iRPos:Integer):String;<br> Var C,C1:Char; <br> TmpStr,LeftStr,RightStr:String; <br> S:Array of String; <br> I,J,K,iCount,iLeft,iRight,iPos:Integer; <br> Label NextRow ; <br> begin <br> TmpStr:=Copy(Source,iLPos+1,(iRPos -iLPos -1)); <br> iCount:=Length(TmpStr); <br> Result:=''; <br> //MessageBox('aaaa',TmpStr) <br> //-------------------------------------------------------- <br> iLeft:=0 ; iRight:=0 ; iPos:=1 ; J:=0 ; K:=-1; <br> //-------------------------------------------------------- <br> For I:=1 to iCount do begin <br> if K=I then Continue; <br> C:=TmpStr; <br> if C='(' then <br> iLeft:=iLeft+1 <br> else if C=')' then <br> iRight:=iRight+1; <br> //----------------------------------- <br> if (C=',') and (iLeft=iRight) then begin <br> J:=J+1; <br> SetLength(S,J); <br> S[J-1]:=Copy(TmpStr,iPos,(I -iPos)) ; iPos:=I+1; <br> end <br> else if (C='=') and (iLeft=iRight) then begin <br> J:=J+1; <br> SetLength(S,J); <br> S[J-1]:=Copy(TmpStr,iPos,(I -iPos)); <br> J:=J+1; <br> SetLength(S,J); <br> S[J-1]:=C ; iPos:=I+1 <br> end <br> else if (C='>') and (iLeft=iRight) then begin <br> C1:=TmpStr[I+1]; <br> if C1='=' then begin <br> J:=J+1; <br> SetLength(S,J); <br> S[J-1]:=Copy(TmpStr,iPos,(I -iPos)); <br> J:=J+1; <br> SetLength(S,J); <br> S[J-1]:=C+C1 ; iPos:=I+2 ; K:=I+1; <br> end else begin <br> J:=J+1; <br> SetLength(S,J); <br> S[J-1]:=Copy(TmpStr,iPos,(I -iPos)); <br> J:=J+1; <br> SetLength(S,J); <br> S[J-1]:=C ; iPos:=I+1 <br> end ; <br> end else if (C='<') and (iLeft=iRight) then begin <br> C1:=TmpStr[I+1]; <br> if (C1='=') or (C1='>') then begin <br> J:=J+1; <br> SetLength(S,J); <br> S[J-1]:=Copy(TmpStr,iPos,(I -iPos)); <br> J:=J+1; <br> SetLength(S,J); <br> S[J-1]:=C+C1 ; <br> iPos:=I+2 ; <br> K:=I+1; <br> end else begin <br> J:=J+1; <br> SetLength(S,1); <br> S[J-1]:=Copy(TmpStr,iPos,(I -iPos)); <br> J:=J+1; <br> SetLength(S,J); <br> S[J-1]:=C ; <br> iPos:=I+1 <br> end <br> end; <br> end; <br> J:=J+1; <br> SetLength(S,J); <br> S[J-1]:=Copy(TmpStr,iPos,(I -iPos+1)); <br> //----------------Debug-------------------------------- <br> // TmpStr:=''; <br> // For I:=Low(S) to High(S) do TmpStr:=TmpStr+'['+S+']'; <br> <br> // ShowMessage(TmpStr); <br> //MessageBox(String(J),S[J]) <br> //--------------------------------------------------------- <br> For I:=Low(S) to High(S) do begin <br> if (I=0) or (I=2) then <br> if S[1]='''' then Continue <br> else <br> S:=FloatToStr(MainCalc(S)); <br> if I<>1 then S:=FloatToStr(MainCalc(S)); <br> //MessageBox(String(I),S[J]) <br> end; <br> //-------------------------------------------------------------- <br> LeftStr:=Copy(Source,1,(iLPos -3)); <br> RightStr:=Copy(Source,iRPos+1,(Length(Source) -iRPos)) ; <br> //------------------------------Debug--------------------------- <br> if IsNumber(S[2]) then begin <br> if S[1]='>' then begin <br> if StrToFloat(S[0])>StrToFloat(S[2]) then TmpStr:=S[3] else TmpStr:=S[4]; <br> GoTo NextRow; <br> end ; <br> if S[1]='>=' then begin <br> if StrToFloat(S[0])>=StrToFloat(S[2]) then TmpStr:=S[3] else TmpStr:=S[4]; <br> GoTo NextRow; <br> end ; <br> if S[1]='<' then begin <br> if StrToFloat(S[0])<StrToFloat(S[2]) then TmpStr:=S[3] else TmpStr:=S[4]; <br> GoTo NextRow; <br> end ; <br> if S[1]='<=' then begin <br> if StrToFloat(S[0])<=StrToFloat(S[2]) then TmpStr:=S[3] else TmpStr:=S[4]; <br> GoTo NextRow; <br> end ; <br> if S[1]='<>' then begin <br> if StrToFloat(S[0])<>StrToFloat(S[2]) then TmpStr:=S[3] else TmpStr:=S[4]; <br> GoTo NextRow; <br> end ; <br> if S[1]='=' then begin <br> if StrToFloat(S[0])=StrToFloat(S[2]) then TmpStr:=S[3] else TmpStr:=S[4]; <br> end; <br> end else begin <br> if (S[1]='=') and (S[0]=Copy(S[2],2,Length(S[2])-2)) then <br> TmpStr:=S[3] <br> else <br> TmpStr:=S[4] <br> end ; <br> NextRow: Result:=LeftStr+TmpStr+RightStr ;<br> end;<br>function SSWR(s: real):real;<br>var <br>r1, r2: real; <br>s1, s2: string; <br>begin <br>r1 := int(s); <br>r2 := frac(s); <br>s1 := copy(floattostr(r1), 1, length(floattostr(r1))); <br>if length(floattostr(r2)) >= 5 then <br>begin <br>if strtoint(copy((floattostr(r2)), 5, 1)) >= 5 then <br>if strtoint(copy((floattostr(r2)), 4, 1)) = 9 then <br>if strtoint(copy((floattostr(r2)), 3, 1)) = 9 then <br>begin <br>s1 := inttostr(strtoint(s1) + 1); <br>s2 :=''; <br>end <br>else <br>S2 := inttostr(strtoint(copy((floattostr(r2)), 3, 1)) + 1) <br>else if copy((floattostr(r2)), 3, 1) = '0' then <br>S2 := '0' + inttostr(strtoint(copy(floattostr(r2), 3, 2)) + 1) <br>else s2 := inttostr(strtoint(copy(floattostr(r2), 3, 2)) + 1) <br>else s2 := copy(floattostr(r2), 3, 2); <br>end <br>else s2 := copy(floattostr(r2), 3, 2); <br>result := strtofloat(s1 + '.' + s2);<br>end;<br>end.