error: String and Byte Incompatible - delphi-2007

While compiling my code, it produces "Incompatible types: 'String' and 'Byte'.
I do not see where I define variable as byte.
unitB
function TDatabaseManager.getPortType(portNo:string):String;
var
SQLQuery:TSQLQuery;
begin
result := '';
SQLQuery := TSQLQuery.Create(Nil);
try
SQLQuery.SQLConnection := FSQLConnection;
SQLQuery.SQL.Clear;
SQLQuery.SQL.Text:= 'SELECT '+portNo+' FROM tblmk6ecpu_setupindex AS t1, tblmk6ecpu_setup AS t2';
SQLQuery.SQL.Text := SQLQuery.SQL.Text + ' WHERE t1.BatchNumber = '''+BatchNo+ ''' AND t1.MfgCode = t2.MfgCode';
SQLQuery.SQL.Text := SQLQuery.SQL.Text + ' ORDER By t1.SetupId DESC';
SQLQuery.Active:=true;
if (not(SQLQuery.IsEmpty())) then
result := VarToStr(SQLQuery.FieldValues[portNo]);
finally
SQLQuery.free;
end;
end;
unitA
for i:= 1 to 10 do
begin
portType:=TDatabaseManager.getPortType('Port'+i);
end;
Please advise

In this line:
getPortType('Port'+i);
You are trying to append an integer directly to a string literal. That does not work. You need to change it to this instead:
getPortType('Port'+IntToStr(i));

Related

How to assign values to an array of objects in Delphi

I have an array of TBoek and and a loop that is supposed to assign values to each of the elements of the array. What happens instead is that the array ends up with the exact same values in each index. Perhaps my order of processing is incorrect or I'm incorrectly assigning values to the array, but either way I cannot for the life of me figure it out.
procedure TBoek.MaakArray;
var
i: integer;
sTitel, sOuteur, sISBN, sUitgewer, sPrys, sI: string;
boek: TBoek;
begin
boek := TBoek.Create;
for i := 0 to 9 do
begin
{$REGION 'Parse JSON om eienskappe van boek te kry'}
sI := IntToStr(i);
sTitel := JSONFile.GetValue<string>('items[' + sI + '].volumeInfo.title');
try
sOuteur := JSONFile.GetValue<string>
('items[' + sI + '].volumeInfo.authors[0]');
except
sOuteur := '<none>'
end;
try
sISBN := JSONFile.GetValue<string>
('items[' + sI + '].volumeInfo.industryIdentifiers[1].identifier');
except
sISBN := '<none>'
end;
try
sUitgewer := JSONFile.GetValue<string>
('items[' + sI + '].volumeInfo.publisher');
except
sUitgewer := '<none>'
end;
try
sPrys := JSONFile.GetValue<string>
('items[' + sI + '].saleInfo.listPrice.amount');
except
sPrys := '0';
end;
{$ENDREGION}
arrBoeke[i] := boek;
with arrBoeke[i] do
begin
SetTitel(sTitel);
SetOuteur(sOuteur);
SetISBN(sISBN);
SetUitgewer(sUitgewer);
SetPrys(sPrys);
end;
end;///end of for loop
end;
The Set functions all follow this format:
procedure TBoek.SetTitel(BoekTitel: string);
begin
fTitel := BoekTitel;
end;
This is the GetString function:
function TBoek.GetString: string;
begin
Result := GetTitel + #13#10 + GetOuteur + #13#10 + GetISBN + #13#10 +
GetUitgewer + #13#10 + GetPrys + #13#10 + #13#10;
end;
And the GetTitel,GetOuteur etc. functions all follow the same format:
function TBoek.GetTitel: string;
begin
Result := fTitel;
end;
What I want is to call:
for I := 0 to 9 do
begin
ShowMessage(arrBoeke[i].GetString);
end;
and access the values in the array one at a time, instead each value is the same.

Command Line Parms: Function Return Type As Array?

Here's the current problem:
Executing an uninstall string with command line parameters following this solution:
Here's what we have in the form of non-functioning code:
const MAX_PATH = 260;
function GetUninstallString(): TArrayOfString;
var
sUnInstPath: String;
sUnInstallString: String;
sUnInstallStringPrm: String;
begin
sUnInstPath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#MyAppName}');
sUnInstallString := '';
if not RegQueryStringValue(HKLM, sUnInstPath, 'UninstallString', sUnInstallString) then
RegQueryStringValue(HKCU, sUnInstPath, 'UninstallString', sUnInstallString);
if sUnInstallString = '' Then
Begin
sUnInstPath := ExpandConstant('Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{#MyAppName}');
RegQueryStringValue(HKLM, sUnInstPath, 'UninstallString', sUnInstallString);
End;
if sUnInstallString <> '' Then
Begin
sUnInstallStringPrm:= copy(sUnInstallString, pos(' ', sUnInstallString) + 1, MAX_PATH);
MsgBox(sUnInstallStringPrm, mbInformation, MB_OK);
Delete(sUnInstallString, pos(' ', sUnInstallString), MAX_PATH);
End;
Result := [sUnInstallString, UnInstallStringPrm];
end;
/////////////////////////////////////////////////////////////////////
function IsUpgrade(): Boolean;
begin
Result := (GetUninstallString() <> '');
end;
/////////////////////////////////////////////////////////////////////
function UnInstallOldVersion(): Integer;
var
sUnInstallString: String;
iResultCode: Integer;
begin
// Return Values:
// 1 - uninstall string is empty
// 2 - error executing the UnInstallString
// 3 - successfully executed the UnInstallString
// default return value
Result := 0;
// get the uninstall string of the old app
sUnInstallString := GetUninstallString();
if sUnInstallString <> '' then begin
sUnInstallString := RemoveQuotes(sUnInstallString);
if ShellExec('open', sUnInstallString, '','', SW_SHOW, ewWaitUntilTerminated, iResultCode) then
Result := 3
else
Result := 2;
end else
Result := 1;
end;
/////////////////////////////////////////////////////////////////////
procedure CurStepChanged(CurStep: TSetupStep);
begin
if (CurStep=ssInstall) then
begin
if (IsUpgrade()) then
begin
UnInstallOldVersion();
end;
end;
end;
There is very little info on how to use GetUninstallString in this context. Possible at all?
Not sure if, as an alternative, the string array containing sUnInstallString... can be passed as a parameter within the above fixture, albeit the return type as array appears to fit a little better.
The GetUninstallString is used twice in the code.
In IsUpgrade
and in UnInstallOldVersion.
In IsUpgrade it's only tested for non-empty value.
In UnInstallOldVersion it is executed.
So make the function return whole UninstallString as a simple string.
For IsUpgrade it is enough.
And do the actual parsing to program path and its arguments in the UnInstallOldVersion only.
Also you should:
Handle a situation where there's no space in the string (no parameters)
The path to the uninstaller can contain spaces too (and it typically will as the uninstallers tend to be in Program Files).

Why am I getting an incorrect array size from lazarus?

I have an array that is being created by parsing a semi-colon delimited list.
The splitting of the string into an array works and if I use a for-in and display each element I get the correct results.
procedure badSizeOfDemo(arrayString: String);
var
semiColonSplitLine: TStringList;
begin
semiColonSplitLine:= TStringList.Create;
semiColonSplitLine.StrictDelimiter := true;
semiColonSplitLine.Delimiter:= ';';
semiColonSplitLine.DelimitedText:= arrayString;
showMessage('arrayString: ' + arrayString);
showMessage('size of split line: ' + IntToStr(SizeOf(semiColonSplitLine)));
end;
With the above code I always get the size of the array as '4' even when the arrayString contains ''.
Am I missing something fundamental here?
FURTHER PROCESSING following switch to using .Count
After splitting the array like this I then do a for-in and check that every element can be converted to a number before building an array of integers.
This essentially works, but then when I try to get the size of the integer array I get an illegal qualifier error.
procedure badSizeOfDemo(arrayString: String);
var
semiColonSplitLine: TStringList;
myElement: String = '';
myIntegerArray: array of integer;
count: Integer = 0;
begin
semiColonSplitLine:= TStringList.Create;
semiColonSplitLine.StrictDelimiter := true;
semiColonSplitLine.Delimiter:= ';';
semiColonSplitLine.DelimitedText:= arrayString;
showMessage('arrayString: ' + arrayString);
showMessage('size of split line: ' + IntToStr(semiColonSplitLine.Count));
for myElement in semiColonSplitLine do
begin
Try
showMessage('field from split line: ' + myElement);
myIntegerArray[count]:=StrToInt(myElement);
except
On E : EConvertError do
ShowMessage('Invalid number encountered');
end;
count:=count+1;
end;
showMessage('myIntegerArray now has ' + myIntegerArray.Count + ' elements');
end;

Get Params of a QueryString and their datatypes

Let's say you have an delphi interface that has a TEdit where an user types and SQL Query
SELECT * FROM X WHERE X.A = :A and X.B = :B and X.C= :C
Is there a way to get the types of the :A,:B,:C Params? I managed to get the name of the Params. using this code
procedure TfrmA.Button1Click(Sender: TObject);
var
queryInput, queryOutput , aux : string;
pozitie : Integer;
param : string;
Ch,Chx : Char;
begin
queryInput := TEdit.Text;
queryOutput := StringReplace(queryInput,':','#',[rfReplaceAll, rfIgnoreCase]);
aux := Copy(queryOutput,AnsiPos('#',queryOutput),200);
while Length(aux ) > 0 do begin
if AnsiPos('#',aux ) = 0 then break;
for Ch in aux do
begin
if Ch = ' ' then begin
param := param + ' ';
break
end else param := param + Ch;
end;
ShowMessage(param);
test := Copy(test,2,200);
test := Copy(test,AnsiPos('#',test),200);
end;
end;
Param string will containt now : #A #B #C
Is there anyway I can find out the datatype of the params?
If you are able to use a Adodataset you might use this to get the needed informations.
uses TypInfo;
procedure TForm5.Button1Click(Sender: TObject);
var
i:Integer;
begin
Ads.CommandText := 'Update Adressen set geboren=:birthdate where name=:n and ID=:i';
Memo1.Lines.Clear;
for I := 0 to Ads.Parameters.Count - 1 do
begin
Memo1.Lines.Add(Ads.Parameters[i].Name + ' : ' + GetEnumName(TypeInfo(TDataType), Integer(Ads.Parameters[i].DataType)) + ' : '+ IntToStr(Ads.Parameters[i].Size) )
end;
end;
The Output of the example will be:
birthdate : ftDateTime : 16
n : ftWideString : 40
i : ftInteger : 4

Initiating a SOAP Array on Delphi

I am trying to initialize or create an array of a soap call:
Array_Of_ProductIdentifierClinicalType = array of ProductIdentifierClinicalType;
This is the way that I am trying to initialize it:
Product[0].IdentifierType := Array_Of_ProductIdentifierClinicalType.Create();
When I run the application I get this error: Access Violation at address...
The question would be: How to initialize this soap call??
Thank you for your time!!!!
You can do a WSDL import on: http://axelcarreras.dyndns.biz:3434/WSAlchemy.wsdl
procedure TFrmMain.Button16Click(Sender: TObject);
Var
ExcludeExpiradas: String;
Serv: AlchemyServiceSoap;
req: AlchemyClinical;
element: AlchemyClinicalRequest;
Prescribed: PrescribedType;
//Prescribing: Prescribing
Prescribing: PrescribedType;
alc: AlchemyIdentifierType;
D: TXSDate;
Counter: Integer;
ProductStr: AlchemyIdentifierClinicalType;
begin
With DM do
begin
ExcludeExpiradas := ' and (' + chr(39) + DateToStr(Date) + chr(39) + ' < (FECHARECETA + 180)) ';
CDSRx_Procesadas.Close;
CDSRx_Procesadas.CommandText := 'SELECT * ' +
' FROM RX_PROCESADAS WHERE ' +
' (NUMERORECETA IS NOT NULL AND CANTIDAD_DISPONIBLE > 0)' +
ExcludeExpiradas +
' and NumeroCliente = ' + CDSPacientesNumeroCliente.asString +
' Order by NumeroReceta';
//ShowMessage(CDSRx_Procesadas.CommandText);
CDSRx_Procesadas.Open;
ProductStr := AlchemyIdentifierClinicalType.Create;
With ProductStr do
begin
Identifier := 1;
end;
element := AlchemyClinicalRequest.Create;
//Prescribed := PrescribedType.Create;
With element do
begin
With Prescribed do
begin
Counter := 0;
while not CDSRx_Procesadas.eof do
begin
Product := Array_Of_ProductIdentifierClinicalType.Create();
With Product[0] do
begin
IdentifierType := ProductIdentifierTypeEnum.NDC9;
Identifier := Copy(DM.CDSInventarioNDC.Value, 1, 9);
end;
Counter := Counter + 1;
CDSRx_Procesadas.Next;
end;
end;
With Prescribing do
begin
Counter := 0;
Product[0].IdentifierType := ProductIdentifierTypeEnum.AlchemyProductID;
Product[0].Identifier := Copy(DM.CDSInventarioNDC.Value, 1, 9);
Counter := Counter + 1;
end;
With PatientDemographics do
begin
while not CDSAlergies.Eof do
begin
Allergy.AllergySubstanceClass[0].Identifier := CDSAlergiesNOALERGIA.Value;
CDSAlergies.Next;
end;
if CDSPacientesSEXO.Value = 1 then
Gender := GenderTypeEnum.Male
else
Gender := GenderTypeEnum.Female;
D := TXSDate.Create;
D.AsDate := CDSPacientesFECHANACIMIENTO.AsDateTime;
DateOfBirth := D;
end;
With RequestedOperations do
begin
DrugToDrug := True;
//DuplicateTherapy
Allergy := True;
With WarningLabels do
begin
Request := True;
LanguageCode := 'en-US';
MaxLines := 5;
CharsPerLine := 24;
end;
With DoseScreening do
begin
Request := True;
end;
AdverseReactions.Request := True;
end;
IgnorePrescribed := False;
IncludeConsumerNotes := True;
IncludeProfessionalNotes := True;
end;
end;
end;*
Assuming that this line of code from the question is accurate:
Array_Of_ProductIdentifierClinicalType = array of ProductIdentifierClinicalType;
then the problem lies here:
Product := Array_Of_ProductIdentifierClinicalType.Create();
This is a dynamic array constructor. It creates a dynamic array of length equal to the number of parameters to the constructor. And then assigns each element of the array, in turn, to the parameters passed.
Consider an example using TBytes = array of Byte.
Bytes := TBytes.Create(1, 2, 3);
This initialises Bytes to be an array of length 3 and having values 1, 2 and 3.
Now, let's look at your code again. This initialises Product to be an array of length 0. So when you access Product[0] that results in a runtime error because the array index is out of bounds.
To solve the problem you will need to make sure that the array is initialised to have sufficient elements. One option is certainly to use a dynamic array constructor. Another is to use SetLength. I suspect that your understanding of Delphi's dynamic arrays is poor. I suggest that you consult the documentation.

Resources