这个问题好象只能用递归算法,应该不算太难,请大家看一看怎么去实现。高分悬赏!!(200分)

  • 主题发起人 主题发起人 filter
  • 开始时间 开始时间
F

filter

Unregistered / Unconfirmed
GUEST, unregistred user!
不知道能不能描述清楚。我需要设计一个报表之间互相取公式的功能,采用华表组件作
为报表工具。所有公式描述都是字符串,单项公式有ZW(最终得到数据的公式),BB(取其它表单
元格公式的公式)。假定有这样一个字符串'BB( "a2","1-天","C" )+BB( "a2","1-天","C" ),
',其实是一个复合公式。其中BB("a2","1-天","C")取a2表中'1-天'行c列的公式,取到结果为
BB("a1","1-甲","d")+zw('pre','2001','3'),即这个字符串应变为
BB("a1","1-甲","d")+zw('pre','2001','3')+BB( "a2","1-天","C" ),直到最后所有的BB公
式都化为了zw()
我想的算法应是这样,每次替换完毕后都检查字符串中有无BB,如有,则剃归。但新问题又
出现。我如何从这样一个字符串中确定BB公式的开始和结尾,BB长度不定,可能还包括其它
先后计算顺序的括号。
例:(不管BB中有几层嵌套,最后一定会得出全部是zw()公式,这就是我想要的结果)
300-(BB("a1","1-甲","d")+zw('pre','2001','3'))*4
然后将其提出来,再用这个BB
找到的公式去替换它。
 
function Parse:String;
var
formula:TStringlist;
I:Integer;
function SearchBB(S:string):TStringList;
begin
//...
end;
function ParseBB(Var L:TStringlist);
Var
I:Integer;
begin
for I:=0 to L.Count-1 do
if Pos('BB',L.Strings)>0 then
begin
L.Objects:=SearchBB;
ParseBB(TStringList(L.Objects));
end;
end;
function BuildFormula(L:TStringlist):String;
Var
I:Integer;
begin
for I:=0 to L.Count-1 do
if L.Objects<>Nil then
Result:=Result+'+('+BuildFormula(TStringList(L.Objects))+')';
else
Result:=Result+'+'+L.Strings;
Result:=Copy(Result,2,Length(Result));
end;
begin
formula:=TStringlist.Create;
formula.Text:='BB( "a2","1-天","C" )'+#13+#10+
'BB( "a2","1-天","C" )';
//你来完善吧,把公式输入到列表。
ParseBB(formula);
Result:=BuildFormula(formula);
formula.Free;//还要把每一个Objects释放
end;
代码很粗糙,但希望你能理解意思!
我的主要思想是将公式输入到TStringList,
然后通过TStringList实现一个树型结构进行递归。
 
jifee,看我理解得对不对?
function SearchBB(S:string):TStringList;
function ParseBB(Var L:TStringlist);
function BuildFormula(L:TStringlist):String;
为function Parse:String;的局部函数
searchBB为找到BB把对应的公式,并将公式放置进tstringlist
ParseBB觉得有点问题
for I:=0 to L.Count-1 do
//tstringlist循环
if Pos('BB',L.Strings)>0 then
//如果找到BB,就将BB找到的公式进行替换
begin
L.Objects:=SearchBB;
//用找到的公式替换
ParseBB(TStringList(L.Objects));
//递归直至不出现BB为止
end;
在function BuildFormula(L:TStringlist):String;生成最终全为zw的字符串
for I:=0 to L.Count-1 do

if L.Objects<>Nil then
Result:=Result+'+('+BuildFormula(TStringList(L.Objects))+')';
else
Result:=Result+'+'+L.Strings;
Result:=Copy(Result,2,Length(Result));
这种方式没有考虑到替换后的字符串顺序,如果我还要严格按顺序进行替换,而不是对
tstringlist进行累计相连,因为我还要考虑其中括号所起的计算先后问题
谢谢你的代码,使我有了一个新的思路。
我想在这个基础上再改改代码,希望还能得到你的指正!
另:L.Strings和L.Objects分别指什么?
 
我已经考虑括号的问题了,顺序也应该是正确的(BuildFormula也是递归)。
if L.Objects<>Nil then
Result:=Result+'+('+BuildFormula(TStringList(L.Objects))+')';
else
Result:=Result+'+'+L.Strings;
L.Strings和L.Objects请参阅TStrings的帮助,这是我最喜欢用的对象。
 
这里完善一下,你可以看到TStringList的威力!
formula:=TStringlist.Create;
formula.Text:='BB( "a2","1-天","C" )'+#13+#10+
'BB( "a2","1-天","C" )';
//你来完善吧,把公式输入到列表。
完善后:
formula:=TStringList.Create;
formula.QuoteChar:='';
formula.Delimiter:='+';
formula.DelimitedText:='BB( "a2","1-天","C" )+BB( "a2","1-天","C" )';
 
OH!Sorry
formula.QuoteChar:=' ';
而且,一定先要把空格删去;
While Pos(' ',S)>0 do
Delete(S,Pos(' ',S),1);
 
看我举例
在searchbb置为
l.strings[0]:='zw('a16','2001','101')+(BB( "a2","1-天","C" )-3)/(BB( "a11","2-地","d" )+zw('a16','2001','101'))'
在ParseBB
for I:=0 to L.Count-1 do
//只循环一次
if Pos('BB',L.Strings)>0 then
//如果找到BB,就将BB找到的公式进行替换
begin
L.Objects:=SearchBB();
//用找到的公式替换
ParseBB(TStringList(L.Objects));
//递归直至不出现BB为止
end;
总觉得有点问题,请把你的QQ告诉我好吗?我们公司白天上不了QQ,只有晚上在家里上
我的QQ为79555709

 
既然公式中包含四则运算,而不是单一的加法,那问题就有一点复杂了。
你需要令:
l.strings[0]:=zw('a16','2001','101')
l.strings[1]:=+
l.strings[2]:=(
l.strings[3]:=BB( "a2","1-天","C" )
l.strings[4]:=-
l.strings[5]:=3
l.strings[6]:=)
l.strings[7]:=/
l.strings[8]:=(
l.strings[9]:=BB( "a11","2-地","d" )
l.strings[10]:=+
l.strings[11]:=zw('a16','2001','101')
l.strings[12]:=)
此外:
if L.Objects<>Nil then
Result:=Result+'('+BuildFormula(TStringList(L.Objects))+')'
else
Result:=Result+L.Strings;
 
其实也不必这么复杂,下面函数可实现。不需要用剃归,我试了一天搞定。
再次感谢热心帮助!
function complexformula(gg:string):string;
var s1,s2:string;
s,e,w:integer;
begin
//'zw("a16","2001","101")+(BB( "a2","1-天","C" )-3)/(BB( "a2","1-天","c" )+zw("a16","2001","101"))'
s1:=gg;
while Pos('BB(',s1)> 0 do
begin
w:=length(s1);
s:=Pos('BB(',s1);
e:=pos(')',copy(s1,Pos('BB(',s1),length(s1)));
//截取出的BB公式
s2:=copy(s1,s,e);
Frmcell_design.cell2.SetFormula(1,1,0,s2);
showmessage('欲删去公式为'+copy(s1,s,e));
delete(s1,s,e);
s1:=trim(copy(s1,1,s-1))+trim(gs)+trim(copy(s1,s,w-s));
if Pos('BB(',s1)>0 then
begin
showmessage('剃归');
end//complexformula(s2) end
else
begin
result:=s1;
break;
end;
// delete(),copy(formula,Pos('BB',s1),pos(')',copy(formula,Pos('BB',s1)+2,length(formula));
end;
 

Similar threads

D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
2K
DelphiTeacher的专栏
D
后退
顶部