Does anybody know why the following code does not work with Excel 2010 (Home and Small Business Office Edition) ¿?
procedure TForm1.Button1Click(Sender: TObject);
var
rango : OleVariant;
ExcelObject : TExcelApplication;
ExcelWorksheet : TExcelWorksheet;
LCID : integer;
begin
try
ExcelObject := TExcelApplication.Create (self);
LCID := LOCALE_USER_DEFAULT;
ExcelObject.Workbooks.Add(EmptyParam, LCID);
ExcelWorksheet := TExcelWorksheet.Create(ExcelObject);
ExcelWorksheet.ConnectTo(ExcelObject.Worksheets.Item [1] as _Worksheet);
rango := ExcelWorksheet.Range['B2','B2'];
rango.Font.size := 16;
rango.Font.Bold := True;
rango.Value2 := 'test';
ExcelObject.Visible[lcid] := true;
except
on e: exception do
showmessage(e.message);
end;
end;
A "Not registered class" exception is shown while adding a workbook: "ExcelObject.Workbooks.Add(EmptyParam, LCID);"
This works fine with Office 2010 Proffesional Edition (and older Office Editions) but not with Home and Small Business Edition 2010 Edition.
I know this is really late but I've been fighting with this same error the last two days and finally figured it out (I think). The error is misleading due to crappy error handling in the component.
The clue I had was that it worked perfectly in a different test application on the same machine - so it wasn't a class registration issue.
I get the error (in several places) if I don't have things connected properly. In your case you probably need to do the CONNECT.
E.g.
ExcelObject := TExcelApplication.Create (self);
ExcelObject.Connect;
I've also seen this if you forget to do a ConnectTo call to connect the interfaces together.
E.g.
XlWorkBook.ConnectTo(XlApp.ActiveWorkbook);
Hope this helps someone else.
Related
I wrote a program using IdHTTP and IdFTP but I have a problem. I wrote it on windows XP 32 bit (using Delphi XE4) and the exe file (Project1.exe) works fine. When I try to open it on windows 7 64 bit, the computer gives me an error.
Picture:
It means "You cannot acces to the path or the specified file. Maybe you don't have enough permissions". I've never seen this error before. Here you can see a picture of the folder with source code.
How can I solve my problem?
Here's the code:
function downloadSrc(var aUrl:ansiString):ansiString;
begin
with tIdHttp.create(nil) do begin //Create Indy http object
request.userAgent:=INET_USERAGENT; //Custom user agent string
redirectMaximum:=INET_REDIRECT_MAX; //Maximum redirects
handleRedirects:=INET_REDIRECT_MAX<>0; //Handle redirects
readTimeOut:=INET_TIMEOUT_SECS*1000; //Read timeout msec
try //Catch errors
result:=get(aUrl); //Do the request
if url.port='80' then url.port:=''; //Remove port 80 from final URL
aUrl:=url.getFullURI //Return final URL
except result:='error' end; //Return an error message if failed
free //Free the http object
end
end;
procedure TForm1.FormCreate(Sender: TObject);
var i:integer;
begin
if not(DirectoryExists('C:\mk7vrlist')) then
begin
CreateDir('C:\mk7vrlist');
end;
ComboBox1.Items.BeginUpdate;
for i := 0 to 59 do
begin
ComboBox1.AddItem(IntToStr(40000+i*1000), nil);
end;
ComboBox1.AddItem('99999', nil);
ComboBox1.Items.EndUpdate;
end;
procedure TForm1.Label5Click(Sender: TObject);
begin
ShellExecute(self.WindowHandle,'open',PChar('http://www.mk7vrlist.altervista.org'),nil,nil,SW_SHOWNORMAL);
end;
procedure TForm1.SpeedButton1Click(Sender: TObject);
var s:ansiString;
begin
IdFTP1.Host:= 'mk7vrlist.altervista.org';
IdFTP1.Username:='mk7vrlist';
IdFTP1.Password:=pass;
IdFTP1.Connect;
s:='http://www.mk7vrlist.altervista.org/databases/test.txt';
Memo1.Lines.Add(Edit1.Text+':'+ComboBox1.Text+':'+Edit2.Text);
Memo1.Lines.Add(downloadSrc(s));
Memo1.Lines.SaveToFile('C:\mk7vrlist\test.txt');
IdFTP1.ChangeDir('databases/');
IdFTP1.Put('C:\mk7vrlist\test.txt');
IdFTP1.Quit;
IdFTP1.Disconnect;
Label10.Visible:=True;
Beep;
end;
Assuming your account has administrative rights, right click on your program's icon, and invoke 'run as administrator' - you will get prompted/warned - click yes.
I don't believe the problem is 32->64 bit, but going from XP to Win 7, which by default is more particular about access.
You can set up a shortcut configured always to run it as admin, to avoid the right click step, but you will still get prompted/warned.
CreateDir('C:\mk7vrlist)
Normal users do not have that kind of access to c:\
Do something like this instead (pseudo code):
CreateDir('%temp%\mk7vrlist)
I have the code:
procedure TfrmMain.btnSendClick(Sender: TObject);
var
aMail: TJclEMail;
begin
aMail := TJclEMail.Create;
Screen.Cursor := crHourGlass;
try
aMail.Recipients.Add('service#blabla.com');
aMail.Subject := '[IMPORTANT] blablba';
aMail.Body := 'text text text text';
aMail.Send(True);
finally
Screen.Cursor := crDefault;
aMail.Free;
end;
end;
This throws: MAPI Error: (2) "General MAPI failure"
Any idea?
ps:
OS Windows 7
Outlook 2010
Delphi 2007
I have the same as you, just wrapped inside a class and it is working.
I use to check if MAPI is OK at the first time I execute Send():
function TMAPIPrerequisites.IsClientAvailable: Boolean;
var
SimpleMAPI: TJclSimpleMapi;
begin
SimpleMAPI := TJclSimpleMapi.Create;
try
Result := SimpleMAPI.AnyClientInstalled;
finally
SimpleMAPI.Free;
end;
end;
function TMAPIPrerequisites.IsMapiAvailable: Boolean;
var
SimpleMAPI: TJclSimpleMapi;
begin
SimpleMAPI := TJclSimpleMapi.Create;
try
Result := SimpleMAPI.SimpleMapiInstalled;
finally
SimpleMAPI.Free;
end;
end;
My problem was that my Jedi library wasnt up to date. I search into jedi repository and JclMapi has change in Tue Dec 27 (Mantis 5748: JclMapi incompatibilities with 64-bit.)
Download this changes, re-compile pkg and now works perfectly!
Thank you anyway!!
The above code works fine IF email client is not already running.
After struggling with same problem i found that the MAPI client has to run in same user context as the MAPI server (e-mail client - Thunderbird in my case).
However, if calling from an app started with administrator privileges (for example an app running in the debugger) then the MAPI calls would fail with error code 2. If both caller and email client are running as admin then everything works (but who's crazy enough to run e-mail client as admin these days?).
I have built the worlds dumbest and most simple SOAP server, in about 3 clicks, in visual studio. The exact steps in visual studio 2010: First create a new project as a web application, Then add a new item of type web service. (See accepted answer here for picture.) That soap server service Service1 has a simple method GetData:
A snippet from clientService1.pas, created using WSDL importer...
IService1 = interface(IInvokable)
['{967498E8-4F67-AAA5-A38F-F74D8C7E346A}']
function GetData(const value: Integer): string; stdcall;
function GetDataUsingDataContract(const composite: CompositeType2): CompositeType2; stdcall;
end;
When I try to run this method, like this:
procedure TForm3.Button1Click(Sender: TObject);
var
rio : THTTPRIO;
sv:IService1;
addr : string;
data : string;
begin
//addr := '....'; // url from visual studio 2010 live debug instance.
rio := THTTPRIO.Create(nil);
sv := GetIService1( true, addr, rio );
try
data := sv.GetData( 0);
Button1.Caption := data;
finally
sv := nil;
rio.Free;
end;
end;
The error I get is this:
ESOAPHTTPException:
The handle is in the wrong state for the requested operation -
URL:http://localhost:8732/Design_Time_Addresses/WcfServiceLibrary1/Service1/ -
SOAPAction:http://tempuri.org/IService1/GetData'.
The URL works fine when I paste the url above into a web browser, so the usual answer that the SOAP code in Delphi has the tendency to not notice an HTTP failure, does not seem likely. Rather it seems that I am either (a) experiencing breakage in WinInet (known to happen in some versions of windows), or (b) doing something wrong?
It seems to me that anybody who has visual studio and delphi both installed, should be able to try to get the dummy starter Soap server in Visual Studio talking to the soap client in Delphi, without any effort at all. But I can not figure out the simplest things.
At one time there was a discussion about the error in a conversation now long since deleted from Embarcadero forums, by Bruneau Babet, an embarcadero staffer.
Bruno said:
Hello,
I've posted a patched version of SOAPHTTPTrans.pas that contains a fix
for this issue here:
[forum link redacted, it didn't work anymore anyways, the post is gone]
You may still override the event as described in the C++Builder
section referred; or, much simpler, at least for Delphi users, simply
add the updated SOAPHTTPTrans.pas to your app's project. Let us know
if that does not work for you.
Cheers,
Bruneau
You can get the repair and the notes about it in its original forum formatting from the following pastebin link and on bitbucket so you don't have to extract the file from the surrounding text.
Warren Update 2016: I have been informed by someone who tried to use the fix on Delphi XE that this fix does NOT work for them in Delphi XE. Any further updates to the code in bitbucket that resolve the remaining bugs would be appreciated.
I ran into the The handle is in the wrong state for the requested operation issue in November 2018 using Delphi Tokyo 10.2.3, then looked at the code patch in the pastebin link under Arjen's answer.
That code is very old and the test code no longer works (SOAP service unavailable). Also, it is unclear from Bruneau's code what he patched exactly.
Comparing that source and the one from my Delphi version it seems that these are the (two) required modifications in the HandleWinInetError procedure ('PATCH HERE'):
function THTTPReqResp.HandleWinInetError(LastError: DWord;
Request: HINTERNET;
RaiseError: Boolean): DWord;
function CallInternetErrorDlg: DWord;
var
P: Pointer;
begin
Result := InternetErrorDlg(GetDesktopWindow(), Request, LastError,
FLAGS_ERROR_UI_FILTER_FOR_ERRORS or
FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS or
FLAGS_ERROR_UI_FLAGS_GENERATE_DATA, P);
{ After selecting client certificate send request again,
Note: InternetErrorDlg always returns ERROR_SUCCESS when called with
ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED }
if LastError = ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED then
Result := ERROR_INTERNET_FORCE_RETRY;
end;
const
{ Missing from our WinInet currently }
INTERNET_OPTION_CLIENT_CERT_CONTEXT = 84;
var
Flags, FlagsLen, DWCert, DWCertLen: DWord;
ClientCertInfo: IClientCertInfo;
CertSerialNum: string;
{$IFDEF CLIENT_CERTIFICATE_SUPPORT}
hStore: HCERTSTORE;
CertContext: PCERT_CONTEXT;
{$ENDIF}
begin
{ Dispatch to custom handler, if there's one }
if Assigned(FOnWinInetError) then
Result := FOnWinInetError(LastError, Request)
else
begin
Result := ERROR_INTERNET_FORCE_RETRY;
{ Handle INVALID_CA discreetly }
if (LastError = ERROR_INTERNET_INVALID_CA) and (soIgnoreInvalidCerts in InvokeOptions) then
begin
FlagsLen := SizeOf(Flags);
InternetQueryOption(Request, INTERNET_OPTION_SECURITY_FLAGS, Pointer(#Flags), FlagsLen);
Flags := Flags or SECURITY_FLAG_IGNORE_UNKNOWN_CA;
InternetSetOption(Request, INTERNET_OPTION_SECURITY_FLAGS, Pointer(#Flags), FlagsLen);
end
else if (LastError = ERROR_INTERNET_SEC_CERT_REV_FAILED) and (soIgnoreInvalidCerts in InvokeOptions) then
begin
FlagsLen := SizeOf(Flags);
InternetQueryOption(Request, INTERNET_OPTION_SECURITY_FLAGS, Pointer(#Flags), FlagsLen);
Flags := Flags or SECURITY_FLAG_IGNORE_REVOCATION;
InternetSetOption(Request, INTERNET_OPTION_SECURITY_FLAGS, Pointer(#Flags), FlagsLen);
end
{$IFDEF CLIENT_CERTIFICATE_SUPPORT}
else if (LastError = ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED) and
Supports(Self, IClientCertInfo, ClientCertInfo) and
(ClientCertInfo.GetCertSerialNumber <> '') then
begin
CertSerialNum := ClientCertInfo.GetCertSerialNumber();
hStore := ClientCertInfo.GetCertStore();
if hStore = nil then
begin
hStore := CertOpenSystemStore(0, PChar('MY'));
ClientCertInfo.SetCertStore(hStore);
end;
CertContext := FindCertWithSerialNumber(hStore, CertSerialNum);
if CertContext <> nil then
begin
ClientCertInfo.SetCertContext(CertContext);
InternetSetOption(Request, INTERNET_OPTION_CLIENT_CERT_CONTEXT,
CertContext, SizeOf(CERT_CONTEXT));
end
else
begin
if RaiseError then RaiseCheck(LastError); // PATCH HERE
Result := CallInternetErrorDlg;
end;
end
{$ENDIF}
else if (LastError = ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED) and (soPickFirstClientCertificate in InvokeOptions) then
begin
{ This instructs WinInet to pick the first (a random?) client cerficate }
DWCertLen := SizeOf(DWCert);
DWCert := 0;
InternetSetOption(Request, INTERNET_OPTION_SECURITY_SELECT_CLIENT_CERT,
Pointer(#DWCert), DWCertLen);
end
else
begin
if RaiseError then RaiseCheck(LastError); // PATCH HERE
Result := CallInternetErrorDlg;
end;
end;
end;
Note that the RaiseError procedure parameter was not even used before this patch ;-)
Here is some test code using the SOAP service from NOAA's National Digital Forecast Database (NDFD) SOAP Web Service:
Uses SOAP.SOAPHTTPTrans;
const Request2 =
'<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ndf="http://graphical.weather.gov/xml/DWMLgen/wsdl/ndfdXML.wsdl">' +
' <soapenv:Header/>' +
' <soapenv:Body>' +
' <ndf:NDFDgenByDay soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">' +
' <latitude xsi:type="xsd:decimal">38.9936</latitude>' +
' <longitude xsi:type="xsd:decimal">-77.0224</longitude>' +
' <startDate xsi:type="xsd:date">%tomorrow%</startDate>' +
' <numDays xsi:type="xsd:integer">5</numDays>' +
' <Unit xsi:type="dwml:unitType" xmlns:dwml="http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd">e</Unit>' +
' <format xsi:type="dwml:formatType" xmlns:dwml="http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd">12 hourly</format>' +
' </ndf:NDFDgenByDay>' +
' </soapenv:Body>' +
'</soapenv:Envelope>';
const URL2= 'https://graphical.weather.gov:443/xml/SOAP_server/ndfdXMLserver.php';
procedure TFrmHandleWinINetError.Button1Click(Sender: TObject);
var
RR: THTTPReqResp;
Response: TMemoryStream;
U8: UTF8String;
begin
RR := THTTPReqResp.Create(nil);
try
try
RR.URL := URL2;
RR.UseUTF8InHeader := True;
RR.SoapAction := 'NDFDgenByDay';
Response := TMemoryStream.Create;
RR.Execute(Request2, Response);
SetLength(U8, Response.Size);
Response.Position := 0;
Response.Read(U8[1], Length(U8));
ShowMessage(String(U8));
except
on E:Exception do ShowMessage('ERROR CAUGHT: ' + e.message);
end;
finally
Response.Free;
RR.Free;
end;
end;
end;
Without the patch errors in the tail end of the URL are caught, but errors in the domain name just trigger an empty error message.
With the patch those are also caught.
I have a reported the issue in the RAD Studio Quality Portal under number RSP-21862
Use at your own risk and please report any additional findings.
Addition: The issue was fixed in Dec 2018 in Delphi 10.3 Rio and the Quality Portal issue was closed with the following remark:
In RAD Studio 10.3 the implementation of THTTPReqResp was changed and replaced with THTTPClient. So, this issue no longer applies.
I have not verified this.
I have:
Delphi 2007
Crystal 11
The Delphi 7 version of the Crystal VCL component (latest one I'm aware of, and it compiles fine in D2007)
A very simple test Crystal report, written in Crystal 11, which just dumps a table onto the screen (no selection criteria, no formulas, just straight data)
I tried
Created a new VCL forms app
Dropped the TCrpe component on the form
Set the "ReportName" property to my test report.
I dropped a button on the form, and behind it placed one line:
Crpe1.Execute
If the report has the "Save Data With Report" option turned on, then this works fine.
If I turn that option off, then I need to provide login credentials.
Using this code (which worked fine in Delphi 5 a million years ago):
procedure TForm1.BitBtn1Click(Sender: TObject);
var
logonItem: integer;
begin
Crpe1.LogOnServer.Clear;
logonItem := Crpe1.LogOnServer.Add('MYSERVER.MYDOMAIN.COM');
Crpe1.LogonServer[logonItem].UserID := 'USERNAME';
Crpe1.LogOnServer[logonItem].Password := 'PASSWORD';
Crpe1.LogOnServer[logonItem].DatabaseName := 'MYDATABASE';
Crpe1.Execute;
end;
I get this error:
---------------------------
Project2
---------------------------
Error:536 Error in File C:\REPORT.RPT:
Unable to connect: incorrect log on parameters.
Execute <PEStartPrintJob>.
---------------------------
OK
---------------------------
What am I doing wrong? How can I provide login credentials to the Crystal VCL component in Delphi? My current workaround is pretty ugly, and I have a lot of legacy code to convert. It would be really nice if I could use the VCL component in a straightforward way.
I use the VCL in Delphi 6, works great. But I don't use the LogOnServer property, I use the LogOnInfo.
This works for any report, and reports that contain subreports (as these need the credentials supplying as well):
With CRPE1 Do
Begin
With SubReports Do
Begin
Retrieve;
If (Count > 0) then
For i := 0 To (Count - 1) Do
Begin
ItemIndex := i;
LogOnInfo.Retrieve;
For j := 0 to LogOnInfo.Count - 1 Do
Begin
LogOnInfo[j];
With LogOnInfo Do
Begin
ServerName := MyDataSource;
DatabaseName := DatabasePath;
UserID := DBUser;
Password := sPwd;
End;
End; {For j}
Tables.Retrieve;
End; {For i}
ItemIndex := 0;
End; {With SubReports}
SubReports[0];
End; {With CRPE1}
Here is some old "legacy" code which uses the VCL component:
mCrpe.reportname:=mfilename;
mCrpe.Connect.UserID := CustomReportCurrentUser;
mCrpe.connect.ServerName:='servername';
mCrpe.connect.DataBaseName:='databasename';
mCrpe.connect.propagate:=True;
mCrpe.Connect.Password := CustomReportClientPass;
try
mConnected := mCrpe.Connect.Test;
except
on e: eDBEngineError do begin
showmessage(e.message);
end;
end;
mCrpe.windowbuttonbar.refreshbtn:=true;
mCrpe.discardsaveddata;
mCrpe.Show;
Some time ago I had read the Crystal VCL component was being "sunsetted". Since then I have migrated to the Active X RDC component. It will require the Active X to be installed on your target computers though.
Delphi 6 on Vista service pack 2 seems that can't load imagelist from dfm and save back again in the IDE.
The project with the dfm corrupted can't be rebuilt.
the error when I run the project is:
EReadError Error reading imagelist1.Bitmap: Failed to read ImageList
data from stream
any suggestion?
thanks in advance
Have you done anything funny to your Delphi installation, such as adding a delphi32.exe.manifest file to Delphi's directory in an attempt to make the IDE have XP or Vista theming? Don't do that. If you have that file there, delete it, and you should be back to normal.
The image-list format changed with version 6 of the Common Controls library, and Delphi 6 is not capable of using it. The manifest tells the IDE to use version 6, so when it saves your DFM, it uses that format. Then, when loading, prior versions can't read it anymore.
The problem may be on ImageList_Write of the comctl32.dll
// delphi 6
procedure TCustomImageList.WriteData(Stream: TStream);
var
SA: TStreamAdapter;
begin
SA := TStreamAdapter.Create(Stream);
try
if not ImageList_Write(Handle, SA) then
raise EWriteError.CreateRes(#SImageWriteFail);
finally
SA.Free;
end;
end;
// delphi 2005
procedure TCustomImageList.WriteData(Stream: TStream);
var
SA: TStreamAdapter;
ComCtrlHandle: THandle;
const
ILP_DOWNLEVEL = 1;
begin
if CachedComCtrlVer = 0 then
begin
CachedComCtrlVer := GetFileVersion(comctl32);
if CachedComCtrlVer >= ComCtlVersionIE6 then
begin
ComCtrlHandle := GetModuleHandle(comctl32);
if ComCtrlHandle <> 0 then
ImageListWriteExProc := GetProcAddress(ComCtrlHandle, 'ImageList_WriteEx'); { Do not localize }
end;
end;
SA := TStreamAdapter.Create(Stream);
try
{ See if we should use the new API for writing image lists in the old
format. }
if Assigned(ImageListWriteExProc) then
begin
if ImageListWriteExProc(Handle, ILP_DOWNLEVEL, SA) <> S_OK then
raise EWriteError.CreateRes(#SImageWriteFail)
end
else if not ImageList_Write(Handle, SA) then
raise EWriteError.CreateRes(#SImageWriteFail);
finally
SA.Free;
end;
end;