INNO SETUP Using checkboxes - checkbox

I'm not familiar with Pascal. I would like to show 10 checkbox before installing.
The user can check several checkboxes according to the group of catalogs he wants to install (10 checkboxes = 10 groups of catalogs).
These checkboxes have to be tested in FILES section and in CODE section.
In FILES section only catalogs of a checked group will be installed.
In CODE section, the pictures will be downloaded and unzipped according to the group of catalogs checked.
I made 100 hundred tries but an error occurs because the local variables can not be used in other sections.
Thanks for your Help
Icho
[Languages]
Name: fr; MessagesFile: compiler:Languages\French.isl; LicenseFile: C:\Dev\Phi8\licensefr.TXT
Name: en; MessagesFile: compiler:Default.isl; LicenseFile: C:\Dev\Phi8\licenseen.TXT
[Setup]
#include "C:\Dev\Inno Download Plugin\idp.iss"
#include "C:\Dev\Inno Download Plugin\french.iss"
[Tasks]
Name: "chkbInstallFR"; Description: "France"; MinVersion: 0.0,5.0
Name: "chkbInstallMO"; Description: "Monaco, Andorre, TAAF, SPM"; MinVersion: 0.0,5.0
Name: "chkbInstallBELUX"; Description: "Belgique, Luxembourg"; MinVersion: 0.0,5.0
Name: "chkbInstallSUI"; Description: "Suisse, Liechtenstein"; MinVersion: 0.0,5.0
Name: "chkbInstallITA"; Description: "Italie"; MinVersion: 0.0,5.0
Name: "chkbInstallALL"; Description: "Allemagne"; MinVersion: 0.0,5.0
Name: "chkbInstallEURONU"; Description: "Europa, Nations Unies, sepac"; MinVersion: 0.0,5.0
Name: "chkbInstallILE"; Description: "Ile des Antilles, Pacifique, Océan indien"; MinVersion: 0.0,5.0
Name: "chkbInstallAFR"; Description: "Anciennes colonies françaises"; MinVersion: 0.0,5.0
Name: "chkbInstallBUR"; Description: "Bureaux français en Europe, Asie, Moyen-Orient"; MinVersion: 0.0,5.0
[Dirs]
Name: {app}\Datas
Name: {app}\Pic
Name: {app}\Pic\AN
Name: {app}\Pic\ANE
Name: {app}\Pic\UNY
[Files]
Source: C:\Sources\Phi\Exe\Datas\UNY_BIN20P.s2db; DestDir: {app}\Datas; Flags: ignoreversion; Check: InstallFR;
Source: C:\Sources\Phi\Exe\Datas\UNY_BIN20D.s2db; DestDir: {app}\datas; Flags: onlyifdoesntexist; Check: InstallFR;
Source: C:\Sources\Phi\Exe\Datas\AN_BIN20P.s2db; DestDir: {app}\Datas; Flags: ignoreversion; Check: InstallMO;
Source: C:\Sources\Phi\Exe\Datas\AN_BIN20D.s2db; DestDir: {app}\datas; Flags: onlyifdoesntexist; Check: InstallMO;
Source: C:\Sources\Phi\Exe\Datas\ANE_BIN20P.s2db; DestDir: {app}\Datas; Flags: ignoreversion; Check: InstallMO;
Source: C:\Sources\Phi\Exe\Datas\ANE_BIN20D.s2db; DestDir: {app}\datas; Flags: onlyifdoesntexist; Check: InstallMO;
Source: C:\Dev\Philatelix8\Install\7za.exe; DestDir: "{app}"; Flags: deleteafterinstall;
[Icons]
[Run]
Filename: {app}\7za.exe; Parameters: "x ""{tmp}UNY.zip"" -o""{app}\Pic\UNY"" * -aoa"; Flags: runascurrentuser;
Filename: {app}\7za.exe; Parameters: "x ""{tmp}AN.zip"" -o""{app}\Pic\AN"" * -aoa"; Flags: runascurrentuser;
Filename: {app}\7za.exe; Parameters: "x ""{tmp}ANE.zip"" -o""{app}\Pic\ANE"" * -aoa"; Flags: runascurrentuser;
[INI]
[Code]
{ RedesignWizardFormBegin } // Don't remove this line!
// Don't modify this section. It is generated automatically.
var
chkbInstallFR: TNewCheckBox;
chkbInstallMO: TNewCheckBox;
chkbInstallBELUX: TNewCheckBox;
chkbInstallSUI: TNewCheckBox;
chkbInstallITA: TNewCheckBox;
chkbInstallALL: TNewCheckBox;
chkbInstallEURONU: TNewCheckBox;
chkbInstallILE: TNewCheckBox;
chkbInstallAFR: TNewCheckBox;
chkbInstallBUR: TNewCheckBox;
procedure RedesignWizardForm;
begin
with WizardForm.SelectTasksLabel do
begin
Visible := False;
Left := ScaleX(392);
end;
{ chkbInstallFR }
chkbInstallFR := TNewCheckBox.Create(WizardForm);
with chkbInstallFR do
begin
Parent := WizardForm.WelcomePage;
Left := ScaleX(8);
Top := ScaleY(16);
Width := ScaleX(97);
Height := ScaleY(17);
Checked := True;
Caption := 'France';
end;
{ chkbInstallMO }
chkbInstallMO := TNewCheckBox.Create(WizardForm);
with chkbInstallMO do
begin
Parent := WizardForm.WelcomePage;
Left := ScaleX(8);
Top := ScaleY(40);
Width := ScaleX(97);
Height := ScaleY(17);
Checked := True;
Caption := 'Monaco, Andorre, TAAF, SPM';
end;
{ chkbInstallBELUX }
chkbInstallBELUX := TNewCheckBox.Create(WizardForm);
with chkbInstallBELUX do
begin
Parent := WizardForm.WelcomePage;
Left := ScaleX(8);
Top := ScaleY(64);
Width := ScaleX(97);
Height := ScaleY(17);
Checked := True;
Caption := 'Belgique et Luxembourg';
end;
{ chkbInstallSUI }
chkbInstallSUI := TNewCheckBox.Create(WizardForm);
with chkbInstallSUI do
begin
Parent := WizardForm.WelcomePage;
Left := ScaleX(8);
Top := ScaleY(64);
Width := ScaleX(97);
Height := ScaleY(17);
Checked := True;
Caption := 'Suisse et Liechtenstein';
end;
{ chkbInstallITA }
chkbInstallITA := TNewCheckBox.Create(WizardForm);
with chkbInstallITA do
begin
Parent := WizardForm.WelcomePage;
Left := ScaleX(8);
Top := ScaleY(64);
Width := ScaleX(97);
Height := ScaleY(17);
Checked := True;
Caption := 'Italie';
end;
{ chkbInstallALL }
chkbInstallALL := TNewCheckBox.Create(WizardForm);
with chkbInstallALL do
begin
Parent := WizardForm.WelcomePage;
Left := ScaleX(8);
Top := ScaleY(64);
Width := ScaleX(97);
Height := ScaleY(17);
Checked := True;
Caption := 'Allemagne';
end;
{ chkbInstallEURONU }
chkbInstallEURONU := TNewCheckBox.Create(WizardForm);
with chkbInstallEURONU do
begin
Parent := WizardForm.WelcomePage;
Left := ScaleX(8);
Top := ScaleY(64);
Width := ScaleX(97);
Height := ScaleY(17);
Checked := False;
Caption := 'Europa, Nations Unies, sepac';
end;
{ chkbInstallILE }
chkbInstallILE := TNewCheckBox.Create(WizardForm);
with chkbInstallILE do
begin
Parent := WizardForm.WelcomePage;
Left := ScaleX(8);
Top := ScaleY(64);
Width := ScaleX(97);
Height := ScaleY(17);
Checked := True;
Caption := 'Iles des antilles, Pacifique et Océan indien';
end;
{ chkbInstallAFR }
chkbInstallAFR := TNewCheckBox.Create(WizardForm);
with chkbInstallAFR do
begin
Parent := WizardForm.WelcomePage;
Left := ScaleX(8);
Top := ScaleY(64);
Width := ScaleX(97);
Height := ScaleY(17);
Checked := True;
Caption := 'Colonies françaises en Afrique';
end;
{ chkbInstallBUR }
chkbInstallBUR := TNewCheckBox.Create(WizardForm);
with chkbInstallBUR do
begin
Parent := WizardForm.WelcomePage;
Left := ScaleX(8);
Top := ScaleY(64);
Width := ScaleX(97);
Height := ScaleY(17);
Checked := True;
Caption := 'Bureaux français en Europe, Asie, Moyen-Orient';
end;
chkbInstallFR.TabOrder := 0;
chkbInstallMO.TabOrder := 1;
chkbInstallBELUX.TabOrder := 2;
chkbInstallSUI.TabOrder := 3;
chkbInstallITA.TabOrder := 4;
chkbInstallALL.TabOrder := 5;
chkbInstallEURONU.TabOrder := 6;
chkbInstallILE.TabOrder := 7;
chkbInstallAFR.TabOrder := 8;
chkbInstallBUR.TabOrder := 9;
{ ReservationBegin }
// This part is for you. Add your specialized code here.
if chkbInstallFR.checked then
begin
idpAddFile('http://www.philatelix.fr/Divers/PHI/UNY.zip', ExpandConstant('{tmp}UNY.zip'));
end;
if chkbInstallMO.checked then
begin
idpAddFile('http://www.philatelix.fr/Divers/PHI/AN.zip', ExpandConstant('{tmp}AN.zip'));
idpAddFile('http://www.philatelix.fr/Divers/PHI/ANE.zip', ExpandConstant('{tmp}ANE.zip'));
end;
{ ReservationEnd }
end;
// Don't modify this section. It is generated automatically.
{ RedesignWizardFormEnd } // Don't remove this line!
procedure InitializeWizard;
begin
{ Download after "Ready" wizard page }
idpDownloadAfter(wpReady);
end;
procedure CurStepChanged(CurStep: TSetupStep);
begin
if CurStep = ssPostInstall then
begin
if chkbInstallFR.checked then
begin
FileCopy(ExpandConstant('{tmp}\UNY.zip'), ExpandConstant('{app}\UNY.zip'), false);
end;
if chkbInstallMO.checked then
begin
FileCopy(ExpandConstant('{tmp}\AN.zip'), ExpandConstant('{app}\AN.zip'), false);
FileCopy(ExpandConstant('{tmp}\ANE.zip'), ExpandConstant('{app}\ANE.zip'), false);
end;
end;
end;
function InstallFR: Boolean;
begin
if chkbInstallFR.checked then
begin
Result := TRUE
end;
else
begin
Result := FALSE
end;
else
end;
function InstallMO: Boolean;
begin
if chkbInstallMO.checked then
begin
Result := TRUE
end;
else
begin
Result := FALSE
end;
end;

with the following code, the checkboxes are displaid exactly where i want but :
The source files are not installed
The installer downloads all ZIP files
I don't know how to arrange the code for the source files are copied and the ZIP are downloaded according to the checkboxes.
[Setup]
OutputBaseFilename=Install_Phi_21
...
DisableWelcomePage=no
WizardImageFile=logoPHI.bmp
;
#include "C:\Dev\Inno Download Plugin\idp.iss"
#include "C:\Dev\Inno Download Plugin\french.iss"
[Tasks]
Name: desktopicon; Description: Créer une &icône sur le bureau; GroupDescription: Additional icons:
[Dirs]
Name: {app}\Pic
Name: {app}\Pic\FR
Name: {app}\Pic\MO
[Files]
...
Source: C:\Sources\Phi\Exe\Datas\UNY_BIN20P2D.s2db; DestDir: {app}\Datas; Flags: ignoreversion; Check: InstallFR;
Source: C:\Sources\Phi\Exe\Datas\UNY_BIN20D.s2db; DestDir: {app}\datas; Flags: onlyifdoesntexist; Check: InstallFR;
Source: C:\Sources\Phi\Exe\Datas\AN_BIN20P2D.s2db; DestDir: {app}\Datas; Flags: ignoreversion; Check: InstallMO;
Source: C:\Sources\Phi\Exe\Datas\AN_BIN20D.s2db; DestDir: {app}\datas; Flags: onlyifdoesntexist; Check: InstallMO;
Source: C:\Sources\Phi\Exe\Datas\ANE_BIN20P2D.s2db; DestDir: {app}\Datas; Flags: ignoreversion; Check: InstallMO;
Source: C:\Sources\Phi\Exe\Datas\ANE_BIN20D.s2db; DestDir: {app}\datas; Flags: onlyifdoesntexist; Check: InstallMO;
Source: C:\Dev\Phi\Install\7za.exe; DestDir: "{app}"; Flags: deleteafterinstall;
[Run]
Filename: {app}\7za.exe; Parameters: "x ""{tmp}UNY.zip"" -o""{app}\Pic\UNY"" * -aoa"; Flags: runascurrentuser;
Filename: {app}\7za.exe; Parameters: "x ""{tmp}AN.zip"" -o""{app}\Pic\AN"" * -aoa"; Flags: runascurrentuser;
Filename: {app}\7za.exe; Parameters: "x ""{tmp}ANE.zip"" -o""{app}\Pic\ANE"" * -aoa"; Flags: runascurrentuser;
[INI]
Filename: {app}\phi.url; Section: InternetShortcut; Key: URL; String: http://www.phi.com
[Code]
var
Page : TWizardPage;
chkbInstallFR: TCheckBox;
chkbInstallMO: TCheckBox;
chkbInstallBELUX: TCheckBox;
chkbInstallSUI: TCheckBox;
chkbInstallITA: TCheckBox;
chkbInstallALL: TCheckBox;
chkbInstallEURONU: TCheckBox;
chkbInstallILE: TCheckBox;
chkbInstallAFR: TCheckBox;
chkbInstallBUR: TCheckBox;
procedure RPage;
begin
Page := CreateCustomPage(wpWelcome, 'Sélection des pays','');
chkbInstallFR := TCheckBox.Create(Page);
chkbInstallFR.Top := ScaleY(8);
chkbInstallFR.Left := ScaleX(0);
chkbInstallFR.Width := Page.SurfaceWidth;
chkbInstallFR.Height := ScaleY(17);
chkbInstallFR.Caption := 'France';
chkbInstallFR.Checked := True;
chkbInstallFR.Parent := Page.Surface;
chkbInstallMO := TCheckBox.Create(Page);
chkbInstallMO.Top := ScaleY(35);
chkbInstallMO.Left := ScaleX(0);
chkbInstallMO.Width := Page.SurfaceWidth;
chkbInstallMO.Height := ScaleY(17);
chkbInstallMO.Caption := 'Monaco, Andorre, TAAF, SPM';
chkbInstallMO.Checked := True;
chkbInstallMO.Parent := Page.Surface;
end;
procedure InitializeWizard;
begin
RPage;
if chkbInstallFR .State= cbchecked then
begin
idpAddFile('http://www.phi.com/Divers/PHI/UNY.zip', ExpandConstant('{tmp}UNY.zip'));
end;
if chkbInstallMO .State= cbchecked then
begin
idpAddFile('http://www.phi.com/Divers/PHI/AN.zip', ExpandConstant('{tmp}AN.zip'));
idpAddFile('http://www.phi.com/Divers/PHI/ANE.zip', ExpandConstant('{tmp}ANE.zip'));
end;
{ Download after "Ready" wizard page }
idpDownloadAfter(wpReady);
end;
procedure CurStepChanged(CurStep: TSetupStep);
begin
if CurStep = ssPostInstall then
begin
if chkbInstallFR .State= cbchecked then
begin
FileCopy(ExpandConstant('{tmp}\UNY.zip'), ExpandConstant('{app}\UNY.zip'), false);
end;
if chkbInstallMO .State= cbchecked then
begin
FileCopy(ExpandConstant('{tmp}\AN.zip'), ExpandConstant('{app}\AN.zip'), false);
FileCopy(ExpandConstant('{tmp}\ANE.zip'), ExpandConstant('{app}\ANE.zip'), false);
end;
end;
end;
function InstallFR: Boolean;
begin
Result := chkbInstallFR .State;
end;
function InstallMO: Boolean;
begin
Result := chkbInstallMO .State;
end;

This is the end of my monologue. I finally did exactly what i want :
Installing some files depending on which checboxes are checked
Downloading and installing ZIP files depending on which checboxes are checked
Advantage of this method, you don't need to download a big install file. The installer will download on your server the needed files.
[Setup]
#include "C:\Dev\Inno Download Plugin\idp.iss"
#include "C:\Dev\Inno Download Plugin\french.iss"
[Dirs]
Name: {app}\Pic
Name: {app}\Pic\FR
Name: {app}\Pic\MO
[Files]
Source: C:\Sources\Phi\Exe\Datas\FR_BIN20P2D.s3db; DestDir: {app}\Datas; Flags: ignoreversion; Check: InstallFR;
Source: C:\Sources\Phi\Exe\Datas\FR_BIN20D.s3db; DestDir: {app}\datas; Flags: onlyifdoesntexist; Check: InstallFR;
Source: C:\Sources\Phi\Exe\Datas\MO_BIN20P2D.s3db; DestDir: {app}\Datas; Flags: ignoreversion; Check: InstallMO;
Source: C:\Sources\Phi\Exe\Datas\MO_BIN20D.s3db; DestDir: {app}\datas; Flags: onlyifdoesntexist; Check: InstallMO;
Source: C:\Sources\Phi\Exe\Datas\AN_BIN20P2D.s3db; DestDir: {app}\Datas; Flags: ignoreversion; Check: InstallMO;
Source: C:\Sources\Phi\Exe\Datas\AN_BIN20D.s3db; DestDir: {app}\datas; Flags: onlyifdoesntexist; Check: InstallMO;
Source: C:\Dev\Phi\Install\7za.exe; DestDir: "{app}"; Flags: deleteafterinstall;
[Run]
Filename: {app}\7za.exe; Parameters: "x ""{tmp}CAV.zip"" -o""{app}\Pic\CAV"" * -aoa"; Flags: runascurrentuser; Check: InstallFR;
Filename: {app}\7za.exe; Parameters: "x ""{tmp}SIC.zip"" -o""{app}\Pic\SIC"" * -aoa"; Flags: runascurrentuser; Check: InstallMO;
[Code]
{ RedesignWizardFormBegin } // Don't remove this line!
// Don't modify this section. It is generated automatically.
var
Page : TWizardPage;
chkbInstallFR: TCheckBox;
chkbInstallMO: TCheckBox;
chkbInstallBELUX: TCheckBox;
chkbInstallSUI: TCheckBox;
chkbInstallITA: TCheckBox;
chkbInstallALL: TCheckBox;
chkbInstallEURONU: TCheckBox;
chkbInstallILE: TCheckBox;
chkbInstallAFR: TCheckBox;
chkbInstallBUR: TCheckBox;
procedure RPage;
begin
Page := CreateCustomPage(wpSelectComponents, 'Sélection des pays','');
chkbInstallFR := TCheckBox.Create(Page);
chkbInstallFR.Top := ScaleY(8);
chkbInstallFR.Left := ScaleX(0);
chkbInstallFR.Width := Page.SurfaceWidth;
chkbInstallFR.Height := ScaleY(17);
chkbInstallFR.Caption := 'France';
chkbInstallFR.Checked := True;
chkbInstallFR.Parent := Page.Surface;
chkbInstallMO := TCheckBox.Create(Page);
chkbInstallMO.Top := ScaleY(35);
chkbInstallMO.Left := ScaleX(0);
chkbInstallMO.Width := Page.SurfaceWidth;
chkbInstallMO.Height := ScaleY(17);
chkbInstallMO.Caption := 'Monaco, Andorre, TAAF, SPM';
chkbInstallMO.Checked := True;
chkbInstallMO.Parent := Page.Surface;
chkbInstallBELUX := TCheckBox.Create(Page);
chkbInstallBELUX.Top := ScaleY(62);
chkbInstallBELUX.Left := ScaleX(0);
chkbInstallBELUX.Width := Page.SurfaceWidth;
chkbInstallBELUX.Height := ScaleY(17);
chkbInstallBELUX.Caption := 'Belgique, Luxembourg';
chkbInstallBELUX.Checked := True;
chkbInstallBELUX.Parent := Page.Surface;
chkbInstallSUI := TCheckBox.Create(Page);
chkbInstallSUI.Top := ScaleY(89);
chkbInstallSUI.Left := ScaleX(0);
chkbInstallSUI.Width := Page.SurfaceWidth;
chkbInstallSUI.Height := ScaleY(17);
chkbInstallSUI.Caption := 'Suisse, Liechtenstein';
chkbInstallSUI.Checked := True;
chkbInstallSUI.Parent := Page.Surface;
chkbInstallITA := TCheckBox.Create(Page);
chkbInstallITA.Top := ScaleY(116);
chkbInstallITA.Left := ScaleX(0);
chkbInstallITA.Width := Page.SurfaceWidth;
chkbInstallITA.Height := ScaleY(17);
chkbInstallITA.Caption := 'Italie';
chkbInstallITA.Checked := True;
chkbInstallITA.Parent := Page.Surface;
chkbInstallALL := TCheckBox.Create(Page);
chkbInstallALL.Top := ScaleY(143);
chkbInstallALL.Left := ScaleX(0);
chkbInstallALL.Width := Page.SurfaceWidth;
chkbInstallALL.Height := ScaleY(17);
chkbInstallALL.Caption := 'Allemagne';
chkbInstallALL.Checked := True;
chkbInstallALL.Parent := Page.Surface;
chkbInstallEURONU := TCheckBox.Create(Page);
chkbInstallEURONU.Top := ScaleY(170);
chkbInstallEURONU.Left := ScaleX(0);
chkbInstallEURONU.Width := Page.SurfaceWidth;
chkbInstallEURONU.Height := ScaleY(17);
chkbInstallEURONU.Caption := 'Europa, Nations Unies, sepac';
chkbInstallEURONU.Checked := True;
chkbInstallEURONU.Parent := Page.Surface;
chkbInstallILE := TCheckBox.Create(Page);
chkbInstallILE.Top := ScaleY(197);
chkbInstallILE.Left := ScaleX(0);
chkbInstallILE.Width := Page.SurfaceWidth;
chkbInstallILE.Height := ScaleY(17);
chkbInstallILE.Caption := 'Iles des antilles, Pacifique et Océan indien';
chkbInstallILE.Checked := True;
chkbInstallILE.Parent := Page.Surface;
chkbInstallAFR := TCheckBox.Create(Page);
chkbInstallAFR.Top := ScaleY(8);
chkbInstallAFR.Left := ScaleX(210);
chkbInstallAFR.Width := Page.SurfaceWidth;
chkbInstallAFR.Height := ScaleY(17);
chkbInstallAFR.Caption := 'Anciennes colonies françaises en Afrique';
chkbInstallAFR.Checked := True;
chkbInstallAFR.Parent := Page.Surface;
chkbInstallBUR := TCheckBox.Create(Page);
chkbInstallBUR.Top := ScaleY(35);
chkbInstallBUR.Left := ScaleX(210);
chkbInstallBUR.Width := Page.SurfaceWidth;
chkbInstallBUR.Height := ScaleY(17);
chkbInstallBUR.Caption := 'Bureaux français à l''étranger';
chkbInstallBUR.Checked := True;
chkbInstallBUR.Parent := Page.Surface;
end;
procedure InitializeWizard;
begin
RPage;
end;
procedure CurStepChanged(CurStep: TSetupStep);
begin
if CurStep = ssInstall then //essayer ssInstall au lieu de ssPostInstall
begin
if chkbInstallFR .State= cbchecked then
begin
FileCopy(ExpandConstant('{tmp}\CAV.zip'), ExpandConstant('{app}\CAV.zip'), false);
end;
if chkbInstallMO .State= cbchecked then
begin
FileCopy(ExpandConstant('{tmp}\SIC.zip'), ExpandConstant('{app}\SIC.zip'), false);
end;
end;
end;
function NextButtonClick(CurPageID: Integer): Boolean;
begin
result := True;
case CurPageID of
100:
begin
if chkbInstallFR .State= cbchecked then
begin
idpAddFile('http://www.phi.com/PHI/CAV.zip', ExpandConstant('{tmp}CAV.zip'));
end
else
begin
msgbox('Not France!',mbError, MB_OK)
end;
if chkbInstallMO .State= cbchecked then
begin
idpAddFile('http://www.phi.com/PHI/SIC.zip', ExpandConstant('{tmp}SIC.zip'));
end
else
begin
msgbox('Not Monaco!',mbError, MB_OK)
end;
end;
wpSelectTasks:
begin
end;
wpReady:
begin
end;
end;
{ Download after "Ready" wizard page }
idpDownloadAfter(wpReady);
end;
function InstallFR: Boolean;
begin
if chkbInstallFR .State = cbchecked then
begin
Result := TRUE;
end
else
begin
Result := FALSE;
end;
end;
function InstallMO: Boolean;
begin
if chkbInstallMO .State = cbchecked then
begin
Result := TRUE;
end
else
begin
Result := FALSE;
end;
end;

Related

I want to check if there is a specific key in the json object

I want to check if the JSON object has the key "error". If it has, I want to "continue" the loop, otherwise the program can go to all the loop.
This is the JSON:
[
{
"cenario": {
"origem": "",
"out": "SNC",
"country": "",
},
"item": "0015963",
"cod": "17894904009319",
"nat_rec": null
},
{
"item": "0012868",
"error": "product unavailable",
"status": "unavailable",
}
]
How can I check if the object that I'm reading has the key "error" or not?
I tried:
jValue.FindValue('error') // The problem it's going to search for all objects.
jValue.TryGetValue('error', jArray) // if it doesn't find the key in the index that it's searching at the moment, it breaks the application.
I'm doing:
response:= IdHTTP.Get(url);
jValue:= TJsonObject.ParseJSONValue(response);
for x := 0 to 2 do
begin
if jValue.TryGetValue('error', jvalue) then
begin
continue;
end;
memo.Lines.Add('cod_item :' + jValue.GetValue<string>('['+intToStr(x)+'].item'));
memo.Lines.Add('cod: ' + jValue.GetValue<string>('['+intToStr(x)+'].cod'));
end;
In your code, jValue is pointing at a TJSONArray, so when you call TryGetValue('error') on it, you are looking for a field named 'error' on the array itself, which obviously is not going to work. That would only work when called on a TJONObject instead.
You would need to include each object's index when querying for the 'error' field on the array itself, eg:
response := IdHTTP.Get(url);
jValue := TJsonObject.ParseJSONValue(response);
try
jArray := jValue as TJSONArray;
for x := 0 to jArray.Count-1 do
begin
if jArray.FindValue('['+IntToStr(x)+'].error') = nil then
continue;
Memo.Lines.Add('cod_item :' + jArray.GetValue<string>('['+IntToStr(x)+'].item'));
Memo.Lines.Add('cod: ' + jArray.GetValue<string>('['+IntToStr(x)+'].cod'));
end;
finally
jValue.Free;
end;
Alternatively, you can iterate the actual objects in memory instead of searching via paths, eg:
response := IdHTTP.Get(url);
jValue := TJsonObject.ParseJSONValue(response);
try
jArray := jValue as TJSONArray;
for x := 0 to jArray.Count-1 do
begin
jObj := jArray[x] as TJSONObject;
if jObj.GetValue('error') = nil then
begin
Memo.Lines.Add('cod_item :' + jObj.GetValue('item').Value);
Memo.Lines.Add('cod: ' + jObj.GetValue('cod').Value);
end;
end;
finally
jValue.Free;
end;
You can parse it to an array and iterate the array. The two functions HasValueAtObjectKey & GetValueAtObjectKey demonstrate two different ways of checking the object for the key.
program JsonTest;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
System.JSON;
const TEST_JSON = '[' +
' {' +
' "cenario": {' +
' "origem": "",' +
' "out": "SNC",' +
' "country": ""' +
' },' +
' "item": "0015963",' +
' "cod": "17894904009319",' +
' "nat_rec": null' +
' },' +
' {' +
' "item": "0012868",' +
' "error": "product unavailable",' +
' "status": "unavailable"' +
' }' +
']';
function HasValueAtObjectKey(AKeyName: String; AJsonObject: TJsonObject): Boolean;
var
LValue: TJsonValue;
begin
Result := AJsonObject.TryGetValue(AKeyName, LValue);
end;
function GetValueAtObjectKey(AKeyName: String; AJsonObject: TJsonObject; var AHasValue: Boolean): String;
begin
try
Result := AJsonObject.GetValue(AKeyName).Value;
AHasValue := TRUE;
except
AHasValue := FALSE;
end;
end;
begin
try
var LArray := TJSONObject.ParseJSONValue(TEST_JSON) as TJSONArray;
try
var i:=1;
for var LArrayValue in LArray do
begin
var LHasValue: Boolean;
var LErroVal := ValueAtObjectKey('error', (LArrayValue As TJSONObject), LHasValue);
if LHasValue then
Writeln('Object ', i, ' Has error: ', LErroVal)
else
Writeln('Object ', i, ' Has no error: ');
Writeln('Object ', i, ' HasValueAtObjectKey: ', HasValueAtObjectKey('error', (LArrayValue As TJSONObject)));
Inc(i);
end;
finally
LArray.Free;
end;
ReadLn;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.

Set reflect.Value to slice in Go

I try to save a slice of integers of a field. the field is type reflect.Value.
I get the error: cannot use articles (variable of type []int64) as reflect.Value value in argument to field.Set. What can I do to encounter that?
Thank you very much!
for i := 0; i < elem.Type().NumField(); i++ {
structField := elem.Type().Field(i)
tag := structField.Tag.Get("db")
fieldType := structField.Type
fieldName := structField.Name
val, ok := record.Get(fmt.Sprintf("%s", tag))
if ok {
// Ignore nil values
if val == nil {
continue
}
field := elem.FieldByName(fieldName)
if field.IsValid() {
t := fieldType.String()
switch t {
case "string":
field.SetString(val.(string))
case "int64":
field.SetInt(val.(int64))
case "float64":
field.SetFloat(val.(float64))
case "boolean":
field.SetBool(val.(bool))
case "[]int64":
articles := []int64{}
initData := []interface{}{
val,
}
for _, data := range initData {
for _, v := range data.([]interface{}) {
t := v
articles = append(articles, t.(int64))
}
}
//
field.Set(articles)
default:
return fmt.Errorf("Invalid type: %s", t)
}
}
}
The answer of mkopriva: field.Set(reflect.ValueOf(articles))

Can this Delphi code related to an array of function of object be made cleaner?

Regarding this function in Delphi:
function TAudioFileMetadata.LoadTags(const Filename: String; var LastError: Integer; var DetectedFormat: TAudioFormat): Boolean;
type
TLoadFromFunction = function (const Filename: String; var LastError: Integer): Boolean of object;
TLoadFrom = record
Format: TAudioFormat;
Process: TLoadFromFunction;
end;
var
i: Byte;
LoadOrder: array [1..6] of TLoadFrom;
begin
DetectedFormat := afUnknown;
LoadOrder[1].Format := afMp3;
LoadOrder[1].Process := LoadFromMp3;
//...
LoadOrder[6].Format := afApe;
LoadOrder[6].Process := LoadFromApe;
for i := Low(LoadOrder) to High(LoadOrder) do
begin
Result := LoadOrder[i].Process(Filename, LastError);
if Result then
begin
DetectedFormat := LoadOrder[i].Format;
break;
end;
end;
end;
How can I improve my implementation? Can I create/fill the LoadOrder array in one shot (or at least not using 2 lines per TLoadFrom)? Could a const array be used (I don't think so)?
Delphi closures (function|procedure ... of object) are backed by the TMethod record, which you can manipulate at runtime. So try something like this:
function TAudioFileMetadata.LoadTags(const Filename: String; var LastError: Integer; var DetectedFormat: TAudioFormat): Boolean;
type
TLoadFromFunction = function (const Filename: String; var LastError: Integer): Boolean of object;
TLoadFrom = record
Format: TAudioFormat;
ProcessAddr: Pointer;
end;
const
LoadOrder: array[1..6] of TLoadFrom = (
(Format: afMp3; ProcessAddr: #TAudioFileMetadata.LoadFromMp3),
    ...
(Format: afApe; ProcessAddr: #TAudioFileMetadata.LoadFromApe)
);
var
i: Byte;
Process: TLoadFromFunction;
begin
DetectedFormat := afUnknown;
TMethod(Process).Data := Self;
for i := Low(LoadOrder) to High(LoadOrder) do
begin
TMethod(Process).Code := LoadOrder[i].ProcessAddr;
Result := Process(Filename, LastError);
if Result then
begin
DetectedFormat := LoadOrder[i].Format;
Exit;
end;
end;
end;

How to use PL/JSON to parse array data

I am just starting to use PL/JSON and I am able to parse non-array data, such as first name, for example:
json_ext.get_string (json (l_list.get (i)), 'firstName');
However I can't figure out how to parse array data such as addresses, for example:
street1 := json_ext.get_string (json (l_list.get (i)), 'addresses.street1');
does not work.
How would I correctly parse array data, using:
street1 := json_ext.get_string (json (l_list.get (i)), 'addresses.street1');
using as an example?
Here is an example of the JSON:
[
{
"firstName": "Edward",
"middleName": "Wolfgang",
"lastName": "Munster",
"addresses": [
{
"city": "",
"addressType": "home",
"state": "CA",
"street1": "1313 Mockingbird Lane",
"street2": ""
},
{
"city": "",
"addressType": "business",
"state": "CA",
"street1": "123 Morgan Rd.",
"street2": ""
}
],
}
Here is the an example of the code I am using:
BEGIN
SELECT json
INTO l_json
FROM json_table
WHERE id = 1;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
l_json := NULL;
END;
l_list := json_list (l_json);
FOR i IN 1 .. l_list.COUNT
LOOP
--These parse correctly
firstname := json_ext.get_string (json (l_list.get (i)), 'firstName');
middlename := json_ext.get_string (json (l_list.get (i)), 'middleName');
lastname := json_ext.get_string (json (l_list.get (i)), 'lastName');
--These do not parse at all
addresstype := json_ext.get_string (json (l_list.get (i)), 'addresses.addressType');
street1 := json_ext.get_string (json (l_list.get (i)), 'addresses.street1');
street2 := json_ext.get_string (json (l_list.get (i)), 'addresses.street2');
city := json_ext.get_string (json (l_list.get (i)), 'addresses.city');
state := json_ext.get_string (json (l_list.get (i)), 'addresses.state');
The example above didn't work for me. I managed to get the following working.
declare
json_data2 json;
json_data json := json('{ "foo": "bar", "list": [ {"key": "value1"}, {"key": "value2"} ] }');
list_value json_list;
begin
list_value := pljson_ext.get_json_list(json_data, 'list');
dbms_output.put_line('Count = '||list_value.count);
for i in 1 .. list_value.count
loop
-- json_data2 := json(list_value.get(i));
json(list_value.get(i)).get('key').print;
-- dbms_output.put_line('key = ' || json_data2.get('key')); -- "key = value"
-- json_data2.get('key').print;
end loop;
end;
/
It's quite simple. Just retrieve the list and iterate it:
-- {
-- "foo": "bar",
-- "list": [
-- {"key": "value"},
-- {"key": "value"}
-- ]
-- }
declare
json_data json := '<the above JSON>';
list_value json_list;
begin
list_value := json_data.get('list');
for i in 1 .. list_value.count
loop
dbms_output.put_line('key = ' || list_value[i].get('key')); -- "key = value"
end;
end;
/
check this example:
DECLARE
OBJ JSON := JSON( '{"pjDATOS_CITAS":[{"SDACLAVE":"32709","PENDIENTES_CITAR":"3","CANTIDAD":"1"},{"SDACLAVE":"32708","PENDIENTES_CITAR":"3","CANTIDAD":"0"}]}' );
LIST_VALUE JSON_LIST;
BEGIN
LIST_VALUE := JSON_LIST(OBJ.GET('pjDATOS_CITAS'));
FOR I IN 1 .. LIST_VALUE.COUNT LOOP
DBMS_OUTPUT.PUT_LINE( 'SDACLAVE->'||JSON_EXT.GET_STRING( JSON(LIST_VALUE.GET(I)) , 'SDACLAVE') );
DBMS_OUTPUT.PUT_LINE( 'PENDIENTES_CITAR->'||JSON_EXT.GET_STRING( JSON(LIST_VALUE.GET(I)) , 'PENDIENTES_CITAR') );
DBMS_OUTPUT.PUT_LINE( 'CANTIDAD->'||JSON_EXT.GET_STRING( JSON(LIST_VALUE.GET(I)) , 'CANTIDAD') );
DBMS_OUTPUT.PUT_LINE( '-------------------------------------------------' );
END LOOP;
END;
and you need fix your JSON FILE... check this example with your JSON:
DECLARE
OBJ JSON := JSON( '{"info_any": {"middleName": "Wolfgang","lastName": "Munster","addresses": [{"city": "","state": "CA","addressType": "home","street2": "","street1": "1313 Mockingbird Lane"},{"city": "","state": "CA","addressType": "business","street2": "","street1": "123 Morgan Rd."}],"firstName": "Edward"}}' );
LIST_VALUE JSON_LIST;
BEGIN
OBJ := JSON ( OBJ.GET('info_any') );
DBMS_OUTPUT.PUT_LINE( 'middleName->'||JSON_EXT.GET_STRING( OBJ , 'middleName') );
DBMS_OUTPUT.PUT_LINE( 'firstName->' ||JSON_EXT.GET_STRING( OBJ , 'firstName') );
DBMS_OUTPUT.PUT_LINE( 'lastName->' ||JSON_EXT.GET_STRING( OBJ , 'lastName') );
DBMS_OUTPUT.PUT_LINE( '-------------------------------------------------' );
LIST_VALUE := JSON_LIST(OBJ.GET('addresses'));
FOR i IN 1 .. LIST_VALUE.COUNT LOOP
DBMS_OUTPUT.PUT_LINE( 'city->'||JSON_EXT.GET_STRING( JSON(LIST_VALUE.GET(I)) , 'city') );
DBMS_OUTPUT.PUT_LINE( 'state->'||JSON_EXT.GET_STRING( JSON(LIST_VALUE.GET(I)) , 'state') );
DBMS_OUTPUT.PUT_LINE( 'addressType->'||JSON_EXT.GET_STRING( JSON(LIST_VALUE.GET(I)) , 'addressType') );
DBMS_OUTPUT.PUT_LINE( 'street2->'||JSON_EXT.GET_STRING( JSON(LIST_VALUE.GET(I)) , 'street2') );
DBMS_OUTPUT.PUT_LINE( 'street1->'||JSON_EXT.GET_STRING( JSON(LIST_VALUE.GET(I)) , 'street1') );
DBMS_OUTPUT.PUT_LINE( '-------------------------------------------------' );
END LOOP;
END;
Result:
middleName->Wolfgang
firstName->Edward
lastName->Munster
-------------------------------------------------
city->
state->CA
addressType->home
street2->
street1->1313 Mockingbird Lane
-------------------------------------------------
city->
state->CA
addressType->business
street2->
street1->123 Morgan Rd.
-------------------------------------------------

martini & appengine/golang, return memcached JSON data

I am now coding with Martini and AppEngine/Go.
I want to use memcache to serve JSON data.
But the response is invalid JSON format.Why "null" is in the response?
null{"results":[{"Title":"Nikkei225","PriceTime":"2014-04-25 06:28:00 UTC","Price":"14,429.26","Diff":"+24.27(0.1%)"},{"Title":"USD/JPY","PriceTime":"2014-04-25 20:49:00 UTC","Price":"102.12-102.16","Diff":"-0.15(-0.1%)"},{"Title":"EURO/JPY","PriceTime":"2014-04-25 20:49:00 UTC","Price":"141.28-141.32","Diff":"-0.19(-0.1%)"},{"Title":"EURO/USD","PriceTime":"2014-04-25 20:48:00 UTC","Price":"1.3833-1.3836","Diff":"+0.0002(0.0%)"},{"Title":"USD/CNY","PriceTime":"2014-04-25 20:48:00 UTC","Price":"6.2536-6.2546","Diff":"+0.0063(0.1%)"},{"Title":"DJIA","PriceTime":"2014-04-25 07:29:00 UTC","Price":"16,361.46","Diff":"-140.19(-0.8%)"},{"Title":"Nasdaq","PriceTime":"2014-04-25 07:00:00 UTC","Price":"4,075.561","Diff":"-72.777(-1.7%)"},{"Title":"FTSE100","PriceTime":"2014-04-25 07:35:00 UTC","Price":"6,685.69","Diff":"-17.31(-0.2%)"}]}
And console says like below:
http: multiple response.WriteHeader calls
My code is like below.
Retrieve from cache:
c := appengine.NewContext(req)
memcacheKey := "markets"
results := []Result{}
cachedItem, getCacheErr := memcache.JSON.Get(c, memcacheKey,&map[string]interface{}{"results": results})
if getCacheErr != nil && getCacheErr != memcache.ErrCacheMiss {
c.Infof("get cache error")
}
if getCacheErr == nil {
c.Infof("cached data found")
c.Infof("cached data: %v",cachedItem.Value)
r.JSON(200, cachedItem.Object)
} else {
c.Infof("cached data not found")
}
Set to memcache:
client := urlfetch.Client(c)
resp, err := client.Get("http://www.nikkei.com/markets/kaigai/worldidx.aspx")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
indexes := Indexes()
doc, _ := goquery.NewDocumentFromResponse(resp)
doc.Find("div.mk-world_market div table tr").Each(func(_ int, s *goquery.Selection) {
title := s.Find("th").Text()
title = strings.Trim(strings.Replace(title,"※","",-1)," ")
if val,ok := indexes[title]; ok {
price := s.Find("th").Next().Text()
diff := s.Find("td:nth-child(3)").Text()
pricetime := s.Find("td:nth-child(4)").Text()
t := time.Now()
pricetime = StringToTime(pricetime,t)
result := Result{val,pricetime,price,diff}
results = append(results,result)
}
})
item := &memcache.Item{
Key:memcacheKey,
Object: &map[string]interface{}{"results": results},
}
setErr := memcache.JSON.Set(c, item)
if setErr != nil {
c.Infof("set error: %v",setErr)
}
What is wrong with my code?
self-resolution:
What I want to do is below.
m.Get("/api/Markets", func(w http.ResponseWriter,r render.Render,req *http.Request) {
c := appengine.NewContext(req)
memcache_key := "markets"
var item_list []Result
results := []Result{}
_, get_cache_err := memcache.JSON.Get(c,memcache_key,&item_list)
if get_cache_err != nil && get_cache_err != memcache.ErrCacheMiss {
c.Infof("get cache error")
}
if get_cache_err == nil {
c.Infof("cached data found")
c.Infof("cached data: %v",item_list)
results = item_list
} else {
c.Infof("cached data not found")
client := urlfetch.Client(c)
resp, err := client.Get("http://www.nikkei.com/markets/kaigai/worldidx.aspx")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
indexes := Indexes()
doc, _ := goquery.NewDocumentFromResponse(resp)
doc.Find("div.mk-world_market div table tr").Each(func(_ int, s *goquery.Selection) {
title := s.Find("th").Text()
title = strings.Trim(strings.Replace(title,"※","",-1)," ")
if val,ok := indexes[title]; ok {
price := s.Find("th").Next().Text()
diff := s.Find("td:nth-child(3)").Text()
pricetime := s.Find("td:nth-child(4)").Text()
t := time.Now()
pricetime = StringToTime(pricetime,t)
result := Result{val,pricetime,price,diff}
results = append(results,result)
}
})
item_list = results
item := &memcache.Item{
Key:memcache_key,
Object: &item_list,
}
setErr := memcache.JSON.Set(c, item)
if setErr != nil {
c.Infof("set error: %v",setErr)
}
}
r.JSON(200, map[string]interface{}{"results": item_list})
})

Resources