expressionform.pas

来自「胜天财务进销存2003源代码,SQLSERVER版,目前最完整的财务进销存系统.」· PAS 代码 · 共 328 行

PAS
328 行
字号
unit ExpressionForm;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Buttons, ExtCtrls, ComCtrls, EditForm, DB, ADODB, KsSkinEngine,
  KsButtons, KsSkinButtons, KsControls, KsSpeedButtons, KsSkinSpeedButtons,
  KsListBoxs, KsSkinListBoxs, KsGroupBoxs, KsSkinGroupBoxs, KsPanels,
  KsSkinPanels, BaseForm, Compile_Calc, KsHooks, KsForms, KsSkinForms, dxCntner,
  dxEditor, dxExEdtr, dxEdLib;

type
  TfrmExpression = class(TfrmEditForm)
    GroupBox2: TSeSkinGroupBox;
    ListBox: TSeSkinListBox;
    GroupBox3: TSeSkinGroupBox;
    sbAdd: TSeSkinSpeedButton;
    sbEec: TSeSkinSpeedButton;
    sbMul: TSeSkinSpeedButton;
    sbDiv: TSeSkinSpeedButton;
    sbLeft: TSeSkinSpeedButton;
    sbRight: TSeSkinSpeedButton;
    sbCheck: TSeSkinButton;
    bbYes: TSeSkinButton;
    bbClear: TSeSkinButton;
    bbExit: TSeSkinButton;
    SeSkinPanel1: TSeSkinPanel;
    Memo1: TdxMemo;
    procedure bbYesClick(Sender: TObject);
    procedure ListBoxDblClick(Sender: TObject);
    procedure sbEecClick(Sender: TObject);
    procedure sbMulClick(Sender: TObject);
    procedure sbDivClick(Sender: TObject);
    procedure sbLeftClick(Sender: TObject);
    procedure sbRightClick(Sender: TObject);
    procedure sbAddClick(Sender: TObject);
    procedure sbCheckClick(Sender: TObject);
    procedure bbClearClick(Sender: TObject);
    procedure bbExitClick(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
  private
    { Private declarations }
    sReturn: string;
    lMode: Integer;
    function CheckExpression(szExp: string): Boolean;
    function ItemToIndex(szExp: string): string;
    procedure LoadGrid;
    procedure LoadData;
    procedure MainRun;
  public
    { Public declarations }
  end;
function GetExpression(szItem: string; szExp: string; l1Mode: Integer = 0): string;
  //返回以ItemIndex为准的公式串
function GetFormulaResult(formula: string): Boolean; //检验公式是否正确
function OperateFormula(Formula: string): Double; //递归实现公式的值
function GetCompileValue(sFormula: string): Double; //使用Compile_Hss类求公式的值

implementation

uses SysPublic, DBData;
{$R *.DFM}

function GetExpression(szItem: string; szExp: string; l1Mode: Integer = 0): string;
var
  frmExpression: TfrmExpression;
begin
  frmExpression := TfrmExpression.Create(Application);
  with frmExpression do
  begin
    ListBox.Items.Text := szItem;
    Memo1.Lines.Text := szExp;
    lMode := l1Mode;
    MainRun;
    Result := sReturn;
    Free;
  end;
end;

procedure TfrmExpression.MainRun;
begin
  bOperateLog := False;
  LoadGrid;
  LoadData;
  ShowModal;
end;

procedure TfrmExpression.LoadGrid;
begin
  sReturn := '';
  case lMode of
    1:
      begin
        sbEec.Visible := False;
        sbMul.Visible := False;
        sbDiv.Visible := False;
        sbLeft.Visible := False;
        sbRight.Visible := False;
      end;
  end;
end;

procedure TfrmExpression.LoadData;
begin
end;

function TfrmExpression.CheckExpression(szExp: string): Boolean;
begin
  szExp := ItemToIndex(szExp);
  Result := GetFormulaResult(szExp);
end;

function TfrmExpression.ItemToIndex(szExp: string): string;
var
  i: Integer;
  szItem: string;
begin
  for i := 0 to ListBox.Items.Count - 1 do
  begin
    szItem := ListBox.Items.Strings[i];
    szExp := StringReplace(szExp, szItem, ' ' + IntToStr(i), [rfReplaceAll]);
  end;
  Result := szExp;
end;

procedure TfrmExpression.bbYesClick(Sender: TObject);
begin
  if Trim(Memo1.lines.Text) = '' then
  begin
    ShowMsg('请输入公式。');
    exit;
  end;
  if CheckExpression(Memo1.lines.Text) then
  begin
    sReturn := Memo1.lines.Text;
    Close;
  end;
end;

procedure TfrmExpression.ListBoxDblClick(Sender: TObject);
begin
  MemoAddStart(Memo1, ListBox.Items.Strings[ListBox.ItemIndex]);
end;

procedure TfrmExpression.sbEecClick(Sender: TObject);
begin
  MemoAddStart(Memo1, '-');
end;

procedure TfrmExpression.sbMulClick(Sender: TObject);
begin
  MemoAddStart(Memo1, '*');
end;

procedure TfrmExpression.sbDivClick(Sender: TObject);
begin
  MemoAddStart(Memo1, '/');
end;

procedure TfrmExpression.sbLeftClick(Sender: TObject);
begin
  MemoAddStart(Memo1, '(');
end;

procedure TfrmExpression.sbRightClick(Sender: TObject);
begin
  MemoAddStart(Memo1, ')');
end;

procedure TfrmExpression.sbAddClick(Sender: TObject);
begin
  MemoAddStart(Memo1, '+');
end;

procedure TfrmExpression.sbCheckClick(Sender: TObject);
begin
  if CheckExpression(Memo1.lines.Text) then
    ShowMsg('公式正确。');
end;

function GetFormulaResult(formula: string): Boolean;
var
  i, j, CountOfBracket: integer;
begin
  result := False;
  CountOfBracket := 0;
  if Trim(formula) = '' then
    exit;
  for i := 1 to Length(formula) do
  begin
    if (i = 1) or (i = Length(formula)) then //检查第一个和最好一个字母的合法性
      if formula[i] in ['+', '-', '*', '/', '.'] then
      begin
        ShowMsg('算式不合法,请重新输入公式。');
        exit;
      end;
    if (formula[i] in ['+', '-', '*', '/', '.']) and (formula[i - 1] in ['+',
      '-', '*', '/', '.']) then
    begin
      ShowMsg('两个运算符相邻出错,请重新输入公式。');
        //检查是否出现两个运算符相邻
      exit;
    end;
    if (formula[i] in ['0'..'9']) then
      // and (formula[i-1] in [' '])and(formula[i-2] in ['0'..'9']) then
    begin
      for j := 1 to i do
      begin
        if (formula[i - j] in [' ']) then
          Continue;
        if (formula[i] = '0') and (formula[i - j] = '/') then
        begin
          ShowMsg('被零除错误,请重新输入公式。');
          exit;
        end;
        if not (formula[i - j] in ['0'..'9']) then
          break;
        ShowMsg('两个项目相邻出错,请重新输入公式。');
        exit;
      end;
    end;
    if (formula[i] = ')') and (formula[i - 1] = '(') then //是否有'()'
    begin
      ShowMsg('出现"()",请重新输入公式。');
      exit;
    end;
    if (ord(formula[i]) < 48) or (ord(formula[i]) > 57) then
      //检查公式中是否含有字母
      if not (formula[i] in ['+', '-', '*', '/', '.', '(', ')', ' ']) then
      begin
        ShowMsg('含有非法字符,请重新输入公式。');
        exit;
      end;
    if formula[i] = '(' then //判断括号前后的合法性
    begin
      inc(CountofBracket);
      if i <> 1 then
        if not (formula[i - 1] in ['+', '-', '*', '/', '(']) then
        begin
          Application.MessageBox('括号前后不匹配,请重新输入公式。', '错误',
            MB_OK);
          exit;
        end;
      if formula[i + 1] in ['+', '-', '*', '/', ')'] then
      begin
        ShowMsg('算式不合法,请重新输入公式。');
        exit;
      end;
    end
    else if formula[i] = ')' then //判断括号前后的合法性
    begin
      dec(CountOfBracket);
      if formula[i - 1] in ['+', '-', '*', '/'] then
      begin
        ShowMsg('括号前后不匹配,请重新输入公式。');
        exit;
      end;
      if i <> length(formula) then
        if not (formula[i + 1] in ['+', '-', '*', '/', ')']) then
        begin
          ShowMsg('算式不合法,请重新输入公式。');
          exit;
        end;
      if CountOfBracket < 0 then
      begin
        ShowMsg('括号前后不匹配,请重新输入公式。');
        exit;
      end;
    end;
  end;
  if CountOfBracket <> 0 then
  begin
    ShowMsg('括号前后不匹配,请重新输入公式。');
    exit;
  end;
  result := True;
end;

function OperateFormula(Formula: string): Double; //递归实现公式的值
var
  sSql: string;
  DataSet: TADODataSet;
begin
  DataSet := TADODataSet.Create(Application);
  sSql := 'SELECT ' + Formula + ' As ExpValue';
  DataSet.LockType := ltReadOnly;
  OpenDataSet(DataSet, sSql);
  if not DataSet.IsEmpty then
  begin
    Result := DataSet.FieldByname('ExpValue').AsFloat;
  end
  else
    Result := 0;
  DataSet.Free;
end;

function GetCompileValue(sFormula: string): Double;
var
  Compilation: TCompile;
begin
  Compilation := TCompile.Create;
  Compilation.SetText(sFormula);
  Result := Compilation.GetValue();
end;

procedure TfrmExpression.bbClearClick(Sender: TObject);
begin
  Memo1.Lines.Clear;
end;

procedure TfrmExpression.bbExitClick(Sender: TObject);
begin
  sReturn := '';
  Close;
end;

procedure TfrmExpression.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if KEY = VK_ESCAPE then
    bbExitClick(Sender);
end;

end.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?