从VBA到Delphi转换(可选参数问题)

时间:2016-09-26 10:17:54

标签: excel-vba delphi vba excel

目前我正在将用VBA编写的项目转换为Delphi,并且偶然发现了使用Optional参数转换一些Subs的问题。 比方说,有一个Sub声明(只是一个例子,实际的Subs有多达10个可选参数):

Sub SetMark
    (x0 As Double, y0 As Double, 
     Optional TextOffset As Integer =5,
     Optional TextBefore As String = "",
     Optional Text As String = "",
     Optional TextAfter As String = "mm",
     Optional Color As String = "FFFFFF",
     Optional ArrowPresent As Boolean = True)

随后可以这样调用Sub:

    Call SetMark (15, 100,,,"135")
    Call SetMark (100, 100, 8,, "My text here..", "")
    'a lot of calls here

Optional参数在这里非常灵活,您可以省略其中任何一个,并且您也可以为其中任何一个赋值。与德尔福不同。

Procedure SetMark
    (x0: real; y0: real, 
            TextOffset: Integer =5;
     TextBefore: ShortString = '';
     Text: ShortString = '';
     TextAfter: ShortString = 'mm';
     Color: ShortString = 'FFFFFF';
     ArrowPresent: Boolean = True);

看来你不能只复制VBA电话:

SetMark (15, 100,,,'135');// error here 

所以,问题是:有没有办法将Subs转换为Delphi程序,保持参数的相同灵活性? 我的第一个想法是使用默认参数,但它不起作用。 至于现在,在Delphi中我似乎必须直接传递列表中的所有参数,但这意味着需要进行大量的工作来审查和正确移植VBA调用。

有什么想法吗?

2 个答案:

答案 0 :(得分:12)

  

有没有办法将VBA子程序转换为Delphi程序,仍然保持参数的相同灵活性?

没有办法实现这一点 - 除了列表末尾之外,省略参数的灵活性根本不存在。

对于自动化对象的方法,您可以使用命名参数,如下所述:Named/optional parameters in Delphi?但是,我非常建议您不要将类实现为自动化对象,只是为了获得该功能。

每当您在语言之间切换时,您会发现不方便的差异。这是不可避免的。最好的方法是尝试找到解决新语言问题的最佳方法,而不是试图将旧语言中的习语强制为新语言。

在这种情况下,您可能希望使用overloaded functionsparameter objects作为缓解此不便的方法。

答案 1 :(得分:2)

为了扩展重构使用参数对象的想法,您可以声明如下记录:

 TSetMarkParams = record
   x0 : double; 
   y0 : double; 
   TextOffset : integer;
   TextBefore : string;
   Text : string;
   TextAfter : string;
   Color : string;
   ArrowPresent : boolean;
   constructor Create(Ax0, Ay0 : double);
 end;

并实现构造函数以将默认值填充为:

 constructor TSetMarkParams.Create(Ax0, Ay0 : double);
 begin
   x0 := Ax0;
   y0 := Ay0;
   TextOffset := 5;
   TextBefore := '';
   Text := '';
   TextAfter := 'mm';
   Color := 'FFFFFF';
   AllowPresent := true;
 end;

您的程序将有签名:

 procedure SetMark(ASetMarkParams : TSetMarkParams);

然后,您可以使用SetMark (15, 100,,,'135');调用的示例:

 var 
   LSetMarkParams : TSetMarkParams
 begin
   LSetMarkParams := TSetMarkParams.Create(15, 100);
   LSetMarkParams.Text := '135';
   SetMark(LSetMarkParams);
 end;

作为附带的好处,上面的内容更具可读性,因为它可以避免在返回调试麻烦的方法调用时盲目尝试计算逗号。