Load text from INI file - text

I want to load text from an external INI file to a TRichEditViewer, but I don't know how.
Here is my code so far (see CH_toolbar.RTFText):
{CH_toolbar}
CH_toolbar := TRichEditViewer.Create(SPPage);
CH_toolbar.Parent := SPPage.Surface;
CH_toolbar.Left := ScaleX(0);
CH_toolbar.Top := Title.Top + Title.Height + 10 ;
CH_toolbar.Width := ScaleX(480);
CH_toolbar.Height := ScaleY(80);
CH_toolbar.TabOrder := 1;
CH_toolbar.Font.Name := 'Verdana';
CH_toolbar.Color := -16777211;
CH_toolbar.ScrollBars := ssVertical;
CH_toolbar.RTFText := ExpandConstant(#ReadIni("setupPages", "setupValues", "SPEulatext", "")) ;
How do I insertSPEulatext value in CH_toolbar.RTFText?

#ReadIni is executed at compile time so it inserts a very long (unquoted) string literal.
If you want to load it at run time, use the GetIniString() function:
CH_toolbar.RTFText := GetIniString('setupValues', 'SPEulatext', '', 'setupPages');
(setupPages is the file name in both cases)
Note that Ini strings have a limited length and can't contain new line characters so an INI file is probably a bad choice for this.
Alternatively, you can load an RTF or text file directly:
ExtractTemporaryFile('lgpl-3.0.txt');
LoadStringFromFile(ExpandConstant('{tmp}/lgpl-3.0.txt'), LGPLText);
LGPLPage.RichEditViewer.RTFText := LGPLText;

Related

How to check if file exist and ask to overwrite in Pascal Script code

function CreateLICStopServiceBatch(): boolean;
begin
Result := true;
fileName := ExpandConstant('{code:GetBasicDirectoryValue}\{code:GetInstance}\_Service\Stop_LIC_Service.bat');
SetArrayLength(lines, 3);
lines[0] := ExpandConstant('set wrapdir={code:GetBasicDirectoryValue}\{code:GetInstance}\_Service');
lines[1] := 'cd /d %wrapdir%';
lines[2] := ExpandConstant('commons-daemon\prunsrv.exe //SS//{code:GetLSDVBServiceNameTEdit}');
Result := SaveStringsToFile(filename,lines,false);
exit;
end;
CreateLICStopServiceBatch();
Right now I'm just writing the file in to the directory, doesn't matter if the file exist or not. But I want to check if the file exist (FileExists) and also have the opportunity to choose (in a dialog) overwrite or take the old file which already exist.
Use FileExists function to test for file existence.
See Inno Setup - Check if file exist in destination or else if doesn't abort the installation
Use MsgBox function for confirmation.
See Inno Setup: Conditionally delete non-empty directory in user's home folder
Side note: Do not use ExpandConstant('{code:Function}') is Pascal code. That makes no sense. Call Function directly. Not to mention that your functions probably do something trivial, which you can inline to your code anyway.
function CreateLICStopServiceBatch(): boolean;
var
FileName: string;
Lines: TArrayOfString;
begin
FileName := GetBasicDirectoryValue + '\' + GetInstance + '\_Service\Stop_LIC_Service.bat';
SetArrayLength(Lines, 3);
Lines[0] := 'set wrapdir=' + GetBasicDirectoryValue + '\' + GetInstance + '\_Service';
Lines[1] := 'cd /d %wrapdir%';
Lines[2] := 'commons-daemon\prunsrv.exe //SS//' + GetLSDVBServiceNameTEdit;
if (not FileExists(FileName)) or
(MsgBox('Overwrite?', mbConfirmation, MB_YESNO) = idYes) then
begin
Result := SaveStringsToFile(FileName, Lines, False);
end
else
begin
{ Not sure what you want to return when user does not confirm overwrite }
Result := False;
end;
end;

inno setup - Create ini key even if it exists

I need to create multiple keys with the same name, without overwriting the existing keys with that name, preferably right below or above them. For example, a key named App already exists in the ini, I need to create another key (or several) named App without overwriting the existing one. As far as I understand that's impossible to do from the [ini] section. So, how can I force create a new key even if it exists?
There is no built-in function for this because what you're asking for breaks the INI file format. In INI files, within each section, every key name must be unique, which you are going to violate. But the following function might do what you want:
[Code]
procedure AppendKey(const FileName, Section, KeyName, KeyValue: string);
var
S: string;
I: Integer;
CurLine: string;
LineIdx: Integer;
SnFound: Boolean;
Strings: TStringList;
begin
Strings := TStringList.Create;
try
S := Format('[%s]', [Section]);
Strings.LoadFromFile(FileName);
SnFound := False;
LineIdx := Strings.Count;
for I := Strings.Count - 1 downto 0 do
begin
CurLine := Trim(Strings[I]);
// if the iterated line is a section, then...
if (Length(CurLine) > 2) and (CurLine[1] = '[') and (CurLine[Length(CurLine)] = ']') then
begin
// if the iterated line is the section we are looking for, then...
if CompareText(S, CurLine) = 0 then
begin
SnFound := True;
Break;
end;
end
else
if CurLine = '' then
LineIdx := I;
end;
if not SnFound then
begin
Strings.Add(S);
Strings.Add(Format('%s=%s', [KeyName, KeyValue]));
end
else
Strings.Insert(LineIdx, Format('%s=%s', [KeyName, KeyValue]));
Strings.SaveToFile(FileName);
finally
Strings.Free;
end;
end;
Call it like:
AppendKey('C:\File.ini', 'Section', 'KeyName', 'KeyValue');

Generating Excel by PL/SQL UTL_FILE, Style error

I'm using ExcelDocTypeUtils pkg for exporting Query data to EXCEL FILE.
When I run the procedure I'm getting a excel file, but when I try to open it this error pops out:
Program came up in the following areas during load: Style
The original line that I think that fails is:
-- Prepare Headers
owa_util.mime_header('application/vnd.ms-excel',FALSE);
I have already tried setting:
<?xml version="1.0" encoding="UTF-8"?>'
But when I do that, the error changes to the following:
Program came up in the following areas during load: 'Strict Parse Error'
Here is how I execute my procedure:
/* Starts */
execute employeereport;
CREATE OR REPLACE PROCEDURE employeeReport AS
v_sql_salary VARCHAR2(200) := 'SELECT last_name,first_name,salary FROM hr.employees ORDER BY last_name,first_name';
v_sql_contact VARCHAR2(200) := 'SELECT last_name,first_name,phone_number,email FROM hr.employees ORDER BY last_name,first_name';
v_sql_hiredate VARCHAR2(200) := 'SELECT last_name,first_name,to_char(hire_date,''MM/DD/YYYY'') hire_date FROM hr.employees ORDER BY last_name,first_name';
excelReport ExcelDocumentType := ExcelDocumentType();
v_worksheet_rec ExcelDocTypeUtils.T_WORKSHEET_DATA := NULL;
v_worksheet_array ExcelDocTypeUtils.WORKSHEET_TABLE := }
ExcelDocTypeUtils.WORKSHEET_TABLE();
documentArray ExcelDocumentLine := ExcelDocumentLine();
v_file UTL_FILE.FILE_TYPE;
BEGIN
-- Salary
v_worksheet_rec.query := v_sql_salary;
v_worksheet_rec.worksheet_name := 'Salaries';
v_worksheet_rec.col_count := 3;
v_worksheet_rec.col_width_list := '25,20,15';
v_worksheet_rec.col_header_list := 'Lastname,Firstname,Salary';
v_worksheet_array.EXTEND;
v_worksheet_array(v_worksheet_array.count) := v_worksheet_rec;
-- Contact
v_worksheet_rec.query := v_sql_contact;
v_worksheet_rec.worksheet_name := 'Contact_Info';
v_worksheet_rec.col_count := 4;
v_worksheet_rec.col_width_list := '25,20,20,25';
v_worksheet_rec.col_header_list := 'Lastname,Firstname,Phone,Email';
v_worksheet_array.EXTEND;
v_worksheet_array(v_worksheet_array.count) := v_worksheet_rec;
-- Contact
v_worksheet_rec.query := v_sql_hiredate;
v_worksheet_rec.worksheet_name := 'Hiredate';
v_worksheet_rec.col_count := 3;
v_worksheet_rec.col_width_list := '25,20,20';
v_worksheet_rec.col_header_list := 'Lastname,Firstname,Hiredate';
v_worksheet_array.EXTEND;
v_worksheet_array(v_worksheet_array.count) := v_worksheet_rec;
owa.num_cgi_vars := NVL(owa.num_cgi_vars, 0);
excelReport := ExcelDocTypeUtils.createExcelDocument(v_worksheet_array);
documentArray := excelReport.getDocumentData;
v_file := UTL_FILE.fopen('C:\','test.xml','W',4000);
FOR x IN 1 .. documentArray.COUNT LOOP
UTL_FILE.put_line(v_file,documentArray(x));
END LOOP;
UTL_FILE.fclose(v_file);
--excelReport.displayDocument;
END;
It's solved.
I don't know what did it, the only thing that I changed it's .xls extension instead of .xml
Thanks.

Delete text after specific character

I have the text inside TEdit box:
'955-986, total = 32'
How would I delete all text after the comma, so it will only left '955-986'
I tried to limit the TEdit Length, but it's not working as I wanted it to be.
What if there'd be no comma? full non-cut string or empty string ?
Below is your idea of limiting string length, but only applied if at least one comma was found.
var
tmpStr:string;
commaPosition:integer;
begin
tmpStr := Edit1.Text;
commaPosition := pos(',',tmpStr);
if commaPosition > 0 then begin
SetLength(tmpStr, commaPosition - 1);
Edit1.Text := tmpStr;
end;
end;
You could use this code:
var
tmpStr:string;
commaPosition:integer;
begin
tmpStr := Edit1.Text;
commaPosition := pos(',',tmpStr);
tmpStr := copy(tmpStr,1,commaPosition-1);
Edit1.Text := tmpStr;
end;
I'm not a Delphi-Programmer (any more). However, I guess you get the String from the Text-Property of your TEdit-Box object, search for the first occurrence of , and get the index thereof and replace the Text contained in your TEdit-Box by the substring from the beginning of the current string to the found index.
edit.Text := Copy(edit.Text, 1, Pos(',', edit.Text)-1);
Sources:
http://docwiki.embarcadero.com/Libraries/en/System.Copy
http://docwiki.embarcadero.com/Libraries/en/System.Pos
TEdit.Text is a property and cannot be passed as var parameter. But once you introduce temporary variable, you can delegate checking of character index returned from Pos to Delete and it will handle all of cases.
var
S: string;
begin
S := Edit1.Text; // try '955-986, total = 32' and '955-986; total = 32'
Delete(S, Pos(',', S), MaxInt);
Edit1.Text := S;
end;

How do I store and load a list of key-value pairs in a string?

I have a list of strings and the values they are to be replaced with. I'm trying to combine them in a list like 'O'='0',' .'='.', ... so it's easy for me to edit it and add more pairs of replacements to make.
Right now the best way I could think of it is:
var
ListaLimpeza : TStringList;
begin
ListaLimpeza := TStringList.Create;
ListaLimpeza.Delimiter := '|';
ListaLimpeza.QuoteChar := '"';
ListaLimpeza.DelimitedText := 'O=0 | " .=."';
ShowMessage('1o Valor = '+ListaLimpeza.Names[1]+' e 2o Valor = '+ListaLimpeza.ValueFromIndex[1]);
This works, but it's not good for visuals, since I can't code the before string (for ex ' .') like that (which is very visual for the SPACE character), only like (" .) so that the = works to assign a name and value in the TStringList.
The Names and Values by default have to be separated by =, in the style of Windows INI files. There's no way AFAICT to change that separator. As #SirRufo indicates in the comment (and which I had never noticed), you can change that using the TStringList.NameValueSeparator property.
This will give you an idea of what Delphi thinks is in your TStringList, which is not what you think it is:
procedure TForm1.FormCreate(Sender: TObject);
var
SL: TStringList;
Temp: string;
i: Integer;
begin
SL := TStringList.Create;
SL.Delimiter := '|';
SL.QuoteChar := '"';
SL.StrictDelimiter := True;
SL.DelimitedText := 'O=0 | ! .!=!.!';
Temp := 'Count: ' + IntToStr(SL.Count) + #13;
for i := 0 to SL.Count - 1 do
Temp := Temp + Format('Name: %s Value: %s'#13,
[SL.Names[i], SL.ValueFromIndex[i]]);
ShowMessage(Temp);
end;
This produces this output:
TStringList Names/Values probably isn't going to do what you need. It's not clear what your actual goal is, but it appears that a simple text file with a simple list of text|replacement and plain parsing of that file would work, and you can easily use TStringList to read/write from that file, but I don't see any way to do the parsing easily except to do it yourself. You could use an array to store the pairs when you parse them:
type
TReplacePair = record
TextValue: string;
ReplaceValue: string;
end;
TReplacePairs = array of TReplacePair;
function GetReplacementPairs: TReplacePairs;
var
ConfigInfo: TStringList;
i, Split: Integer;
begin
ConfigInfo := TStringList.Create;
try
ConfigInfo.LoadFromFile('ReplacementPairs.txt');
SetLength(Result, ConfigInfo.Count);
for i := 0 to ConfigInfo.Count - 1 do
begin
Split := Pos('|`, ConfigInfo[i];
Result[i].TextValue := Copy(ConfigInfo[i], 1, Split - 1);
Result[i].ReplaceValue := Copy(ConfigInfo[i], Split + 1, MaxInt);
end;
finally
ConfigInfo.Free;
end;
end;
You can then populate whatever controls you need to edit/add/delete the replacement pairs, and just reverse the read operation to write them back out to save.

Resources