lazarus/components/lazreport/source/addons/addfunction/frFuncStr.pas
jesus 118cc819c4 LazReport: New big patch from Alexey Lagunov (with small changes)
-------------------------------------------------------
Addfunction / frFuncStr
  - Fixed string functions - accounted for UTF8 strings

DialogControls
  - Fixed reports generation with built-in query mode, MDI (multiple reports open for viewing at the same time)
  - Fixed UNDO in editor
  - Added property HINT for dialog controls
  - A new component - TlrRadioGroup

lrOfficeImport
  - New tool reports designer to import data from a spreadsheet as a report template

source
  - The object TfrMemoView added new handlers
    - OnClick - Event when you click on TfrMemoView in playback mode built reports
    - OnMouseEnter - Event at the Enter of the mouse over TfrMemoView in playback mode built reports
    - OnMouseLeave - Event at the Leave of the mouse TfrMemoView in playback mode built reports

  - The object TfrMemoView added new properties
    - Cursor - the mouse cursor when moving over TfrMemoView in playback mode built reports
    - DetailReport - a reference to the detail-report - called when the user clicks the mouse on TfrMemoView in playback mode built reports

  - A mechanism to detail-report - call a detailed report of the current report
  - In ineterpretatore added new features (for compatibility with FastReport 2.5):
      - FINALPASS
      - CURY
      - PAGEHEIGH
      - PAGEWIDTH
  - In the reports, the editor started saving paramerov editor (the location of the Object Inspector, fonts)
  - In the reports, the editor corrected the addition of new tools (implemented a new tool - Import report template from excel/OpenOffice)
  - Editor of reports finalized Inspector data - now you can also insert variables
  - For export to txt implemented request form export options

images
  - Made in the resources icon tool insert fields in a report from the editor

Demo included (detail_reports)

And new extensions:
- import report template from calc/excel
- send email from report preview (for sending used local mail app, installed on user PC - in windows its TheBat! and Mozilla Thunderbird).
  In future I'm plan make direct send.

git-svn-id: trunk@46079 -
2014-08-28 04:10:20 +00:00

354 lines
11 KiB
ObjectPascal

{*******************************************************}
{ }
{ Add FastReport String Lbrary }
{ }
{ Copyright (c) 1995, 1996 AO ROSNO }
{ Copyright (c) 1997, 1998 Master-Bank }
{ }
{ Copyright (c) 2001 by Stalker SoftWare }
{ }
{*******************************************************}
unit frFuncStr;
interface
{$mode objfpc}
{$B-} {- Complete Boolean Evaluation }
{$R-} {- Range-Checking }
{$V-} {- Var-String Checking }
{$T-} {- Typed @ operator }
{$X+} {- Extended syntax }
{$P+} {- Open string params }
{$J+} {- Writeable structured consts }
{$H+} {- Use long strings by default }
{$DEFINE HASVARIANT}
{.$I LR_Vers.inc}
uses
SysUtils;
type
TfrCharSet = set of Char;
// RxLib
function frWordPosition(const N: Integer; const S: string; const WordDelims: TfrCharSet): Integer;
function frExtractWord(N: Integer; const S: string; const WordDelims: TfrCharSet): string;
function frWordCount(const S: string; const WordDelims: TfrCharSet): Integer;
function frIsWordPresent(const W, S: string; const WordDelims: TfrCharSet): Boolean;
function frNPos(const C: string; S: string; N: Integer): Integer;
function frReplaceStr(const S, Srch, Replace: string): string;
// StLib
function frReplicate(cStr: String; nLen :Integer) :String;
function frPadRight(cStr: String; nLen: Integer; cChar :String) :String;
function frPadLeft(cStr: String; nLen: Integer; cChar :String) :String;
function frPadCenter( cStr: String; nWidth: Integer; cChar: String): String;
function frEndPos(cStr, cSubStr: String) :Integer;
function frCompareStr(cStr1, cStr2: String) :Integer;
function frLeftCopy(cStr: String; nNum: Integer): String;
function frRightCopy(cStr: String; nNum: Integer): String;
// Delphi
function frDelete(cStr: String; nIndex, nCount:Integer) :String;
function frInsert(cStr1, cStr2: String; nIndex:Integer) :String;
implementation
uses LazUTF8;
{--------------------------------------------------------------------}
{ Return position first character N words in string S, use }
{ const WordDelims (type TCharSet) as delimiter between words }
{--------------------------------------------------------------------}
function frWordPosition(const N: Integer; const S: string; const WordDelims: TfrCharSet): Integer;
var
Count, I: Integer;
begin
Count := 0;
I := 1;
Result := 0;
while (I <= Length(S)) and (Count <> N) do begin
{ skip over delimiters }
while (I <= Length(S)) and (S[I] in WordDelims) do Inc(I);
{ if we're not beyond end of S, we're at the start of a word }
if I <= Length(S) then Inc(Count);
{ if not finished, find the end of the current word }
if Count <> N then
while (I <= Length(S)) and not (S[I] in WordDelims) do Inc(I)
else Result := I;
end; { while }
end; { frWordPosition }
{--------------------------------------------------------------------}
{ Extract N word from string S, use WordDelims as }
{ delimiter between words }
{--------------------------------------------------------------------}
function frExtractWord(N: Integer; const S: string; const WordDelims: TfrCharSet): string;
var
I: Integer;
Len: Integer;
begin
Len := 0;
I := frWordPosition(N, S, WordDelims);
if I <> 0 then
{ find the end of the current word }
while (I <= Length(S)) and not(S[I] in WordDelims) do begin
{ add the I'th character to result }
Inc(Len);
SetLength(Result, Len);
Result[Len] := S[I];
Inc(I);
end; { while }
SetLength(Result, Len);
end; { frExtractWord }
{--------------------------------------------------------------------}
{ Count words in string S, use WordDelims as delimiter }
{ between words }
{--------------------------------------------------------------------}
function frWordCount(const S: string; const WordDelims: TfrCharSet): Integer;
var
SLen, I: Cardinal;
begin
Result := 0;
I := 1;
SLen := Length(S);
while I <= SLen do begin
while (I <= SLen) and (S[I] in WordDelims) do Inc(I);
if I <= SLen then Inc(Result);
while (I <= SLen) and not(S[I] in WordDelims) do Inc(I);
end; { while }
end; { frWordCount }
{--------------------------------------------------------------------}
{ Check existing word W in string S, use }
{ WordDelims as possible delimiters between words }
{--------------------------------------------------------------------}
function frIsWordPresent(const W, S: string; const WordDelims: TfrCharSet): Boolean;
var
Count, I: Integer;
begin
Result := False;
Count := frWordCount(S, WordDelims);
for I := 1 to Count do
if frExtractWord(I, S, WordDelims) = W then begin
Result := True;
Exit;
end; { if }
end; { frIsWordPresent }
{--------------------------------------------------------------------}
{ Find position N substring C in string S }
{--------------------------------------------------------------------}
function frNPos(const C: string; S: string; N: Integer): Integer;
var
I, P, K: Integer;
begin
Result := 0;
K := 0;
for I := 1 to N do begin
P := Pos(C, S);
Inc(K, P);
if (I = N) and (P > 0) then begin
Result := K;
Exit;
end; { if }
if P > 0 then Delete(S, 1, P)
else Exit;
end; { for }
end; { frNPos }
{--------------------------------------------------------------------}
{ Function exchange in string S all substrings Srch on }
{ other substring, delivered as Replace. }
{--------------------------------------------------------------------}
function frReplaceStr(const S, Srch, Replace: string): string;
var
I: Integer;
Source: string;
begin
Source := S;
Result := '';
repeat
I := Pos(Srch, Source);
if I > 0 then begin
Result := Result + UTF8Copy(Source, 1, I - 1) + Replace;
Source := UTF8Copy(Source, I + UTF8Length(Srch), MaxInt);
end
else Result := Result + Source;
until I <= 0;
end; { frReplaceStr }
{--------------------------------------------------------------------}
{ Return nLen chars as cStr }
{--------------------------------------------------------------------}
function frReplicate(cStr: String; nLen :Integer) :String;
var
nCou :Integer;
begin
Result := '';
for nCou := 1 to nLen do
Result := Result + cStr;
end; { Replicate }
{--------------------------------------------------------------------}
{ Return string filled chars cChar from left to nLen }
{--------------------------------------------------------------------}
function frPadLeft(cStr: String; nLen: Integer; cChar :String) :String;
var
S :String;
begin
S := Trim(cStr);
Result := frReplicate(cChar, nLen-Length(S))+S;
end ; { frPadLeft }
{--------------------------------------------------------------------}
{ Return string filled chars cChar from right to nLen }
{--------------------------------------------------------------------}
function frPadRight(cStr: String; nLen: Integer; cChar :String) :String ;
var
S :String;
begin
S := Trim(cStr);
Result := S+frReplicate(cChar, nLen-Length(S));
end; { frPadRight }
{--------------------------------------------------------------------}
{ Return centered string filled chars cChar with both side }
{--------------------------------------------------------------------}
function frPadCenter( cStr: String; nWidth: Integer; cChar: String): String;
var
nPerSide :Integer;
cResult :String;
begin
nPerSide := (nWidth - Length(cStr)) div 2;
cResult := frPadLeft(cStr, (Length(cStr) + nPerSide), cChar);
Result := frPadRight(cResult, nWidth, cChar);
end; { frPadCenter }
{----------------------------------------------------------------}
{ Find in string substring from end }
{ Return position substing if found, else return 0 }
{----------------------------------------------------------------}
function frEndPos(cStr, cSubStr: String) :Integer;
var
nCou :Integer;
nLenSS :Integer;
nLenS :Integer;
begin
nLenSS := Length(cSubStr);
nLenS := Length(cStr);
Result := 0 ;
if nLenSS > nLenS then Exit;
for nCou := nLenS downto 1 do
if UTF8Copy( cStr, nCou, nLenSS ) = cSubStr then
begin
Result := nCou;
Exit;
end; { if }
end; { frEndPos }
{--------------------------------------------------------------------}
{ Return substring from first char to nNum }
{--------------------------------------------------------------------}
function frLeftCopy( cStr: String; nNum: Integer ): String;
begin
Result := UTF8Copy( cStr, 1, nNum );
end; { frLeftCopy }
{--------------------------------------------------------------------}
{ Return substring from last char to position nNum }
{--------------------------------------------------------------------}
function frRightCopy( cStr: String; nNum: Integer ): String;
begin
Result := '';
if nNum > Length( cStr ) then Exit;
Result := UTF8Copy( cStr, (UTF8Length(cStr) - nNum + 1), UTF8Length(cStr) );
end; { frRightCopy }
{--------------------------------------------------------------------}
{ Delete nCount chars in string cStr from position nIndex }
{--------------------------------------------------------------------}
function frDelete(cStr: String; nIndex, nCount:Integer) :String;
begin
UTF8Delete(cStr, nIndex, nCount);
Result := cStr;
end; { frDelete }
{--------------------------------------------------------------------}
{ Insert string cStr2 into string cStr1, from position nIndex }
{--------------------------------------------------------------------}
function frInsert(cStr1, cStr2: String; nIndex:Integer) :String;
begin
UTF8Insert(cStr1, cStr2, nIndex);
Result := cStr2;
end; { frDelete }
{----------------------------------------------------------------}
{ Compare cStr1 and cStr2 and return number of the position }
{ difference strings }
{----------------------------------------------------------------}
function frCompareStr(cStr1, cStr2: String) :Integer;
var
nLenMax :Integer;
nCou :Integer;
begin
Result := 0;
if Length( cStr1 ) > Length( cStr2 ) then
nLenMax := Length( cStr1 )
else
nLenMax := Length( cStr2 );
for nCou := 1 to nLenMax do
if UTF8Copy( cStr1, nCou, 1) <> UTF8Copy( cStr2, nCou, 1) then
begin
Result := nCou;
Exit;
end; { if }
end; { frCompareStr }
end.