Opening a second presentation fails - Delphi XE2 + Windows 8 - delphi

Need to an open an PowerPoint presentation. I am using the below statement.
Var
ppt: _Application;
pres: _Presentation;
try
ppt := GetActiveOleObject('PowerPoint.Application') as _Application;
except
ppt := CreateOleObject('PowerPoint.Application') as _Application ;
end;
ppt.Visible := msoTrue;
try
pres := ppt.Presentations.Open(FPOTX, msoFalse, msoTrue, msoTrue);
except
on e:exception do begin
printtofile('Error in call to ppt.Presentation.Open' + e.message);
end;
end;
It works fine whenever , CreateOleObject() in exception is called. (i.e., no presentation is already open).
But the above statement fails , if one presentation is already open. (i.e, ppt.Presentations.Open() is called after GetActiveOleObject() function).
Using Delphi XE2 , MS Office 2013 , Windows 8
This fails only in Windows 8 not in Windows 7.
Thanks in advance.

I don't know where the problem is, if it is your Delphi or Office or Windows version. But this code works no problem in Windows 8.1 x64, Delphi XE2 (32bit target), Office 2007. Unfortunately I do not have Office 2013 to test it.
I don't have any Type LIBs imported in my Delphi. So I tested it just using plain Variant types.
If PPT isn't opened, the code opens it. Otherwise it gets the OLE Object. Afterwards the desired Presentation is opened. Works as often as I tested it, no matter if PPT is closed or opened.
...
implementation
uses
ComObj, ActiveX;
const
msoFalse = TOleEnum(False);
msoTrue = TOleEnum(True);
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
ppt, pres: Variant;
begin
ppt := Unassigned;
pres := Unassigned;
try
ppt := GetActiveOleObject('PowerPoint.Application');
except
ppt := CreateOleObject('PowerPoint.Application');
end;
ppt.Visible := msoTrue;
try
pres := ppt.Presentations.Open('C:\Temp\Test.pptx', msoFalse, msoTrue, msoTrue);
except
on E:Exception do
ShowMessage('OOPS');
end;
end;
EDIT
I also tested it with an imported PowerPoint Type Lib. And your code works 1:1 here:
...
implementation
uses
ComObj, ActiveX, PowerPoint_TLB;
const
msoFalse = TOleEnum(False);
msoTrue = TOleEnum(True);
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
ppt: _Application;
pres: _Presentation;
begin
ppt := nil;
pres := nil;
try
ppt := GetActiveOleObject('PowerPoint.Application') as _Application;
except
ppt := CreateOleObject('PowerPoint.Application') as _Application;
end;
ppt.Visible := msoTrue;
try
pres := ppt.Presentations.Open('C:\Temp\Test.pptx', msoFalse, msoTrue, msoTrue);
except
on E:Exception do
ShowMessage('OOPS');
end;
end;
SOLUTION FOR OFFICE 2013
As you already found out: It seems to work with Office 2013 when changing the Title parameter of ppt.Presentations.Open to msoFalse ==> ppt.Presentations.Open(FPOTX, msoFalse, msoFalse, msoTrue)

This works for me absolutely without any issues. The problem faced was compatibility issue between the XXX.pot(office 1997-2003) and XXX.potx (office2014). Apart from that everthing was fine.

Related

Routine for proxy change does not work on delphi 10.2 Tokyo

I am using using the Raises routine to configure use proxy within the system.
It works perfectly in delphi in version 7. In Delphi 10.2 (Tokyo), even compiling without errors, when calling the routine informs that the proxy is not responding (being that the proxy is ok and worked in delphi 7 call).
Would anyone have any idea what might be going on?
function ApplyProxy(proxy: string):Boolean;
var
MyInternetProxyInfo: PInternetProxyInfo;
begin
try
Result:=False;
proxy:=Trim(proxy);
MyInternetProxyInfo:=New(PInternetProxyInfo);
try
if proxy = EmptyStr then
MyInternetProxyInfo^.dwAccessType := INTERNET_OPEN_TYPE_DIRECT else
begin
MyInternetProxyInfo^.dwAccessType := INTERNET_OPEN_TYPE_PROXY;
MyInternetProxyInfo^.lpszProxy := PAnsiChar(Trim(proxy));
MyInternetProxyInfo^.lpszProxyBypass := PAnsiChar('<local>');
end;
Result:=InternetSetOption(nil, INTERNET_OPTION_PROXY, MyInternetProxyInfo,
SizeOf(MyInternetProxyInfo^));
finally
Dispose(MyInternetProxyInfo);
end;
except
Result:=False;
end;
end;
In Delphi 10.2 Tokyo strings are unicode, and the compiler will warn that
PAnsiChar(Trim(proxy));
is
W1044 Suspicious typecast of string to PAnsiChar.
and this will not work when executed. Convert the string to an AnsiString first.
For example:
MyInternetProxyInfo^.lpszProxy := PAnsiChar(AnsiString(Trim(proxy)));
As suggested by LU-RD, I changed the routine and started running on tokio 10.2 update 3.
function ApplyProxy(proxy: string):Boolean;
var
MyInternetProxyInfo: PInternetProxyInfo;
begin
try
Result:=False;
proxy:=Trim(proxy);
MyInternetProxyInfo:=New(PInternetProxyInfo);
try
if proxy = EmptyStr then
MyInternetProxyInfo^.dwAccessType := INTERNET_OPEN_TYPE_DIRECT else
begin
MyInternetProxyInfo^.dwAccessType := INTERNET_OPEN_TYPE_PROXY;
MyInternetProxyInfo^.lpszProxy := PAnsiChar(AnsiString(Trim(proxy)));
MyInternetProxyInfo^.lpszProxyBypass := PAnsiChar('<local>');
end;
Result:=InternetSetOption(nil, INTERNET_OPTION_PROXY, MyInternetProxyInfo, SizeOf(MyInternetProxyInfo^));
finally
Dispose(MyInternetProxyInfo);
end;
except
Result:=False;
end;
end;

How can I load an HTML string into a Firemonkey TWebBrowser?

I'm trying to use the Firemonkey TWebBrowser to load some HTML that is generated at runtime. The HTML is a Delphi string.
I've looked at some code from: http://delphi.about.com/cs/adptips2004/a/bltip0104_4.htm
procedure WBLoadHTML(WebBrowser: TWebBrowser; HTMLCode: string) ;
var
sl: TStringList;
ms: TMemoryStream;
begin
WebBrowser.Navigate('about:blank') ;
while WebBrowser.ReadyState < READYSTATE_INTERACTIVE do
Application.ProcessMessages;
if Assigned(WebBrowser.Document) then begin
sl := TStringList.Create;
try
ms := TMemoryStream.Create;
try
sl.Text := HTMLCode;
sl.SaveToStream(ms) ;
ms.Seek(0, 0) ;
(WebBrowser.Document as IPersistStreamInit).Load(TStreamAdapter.Create(ms)) ;
finally
ms.Free;
end;
finally
sl.Free;
end;
end;
end;
procedure TForm1.FormCreate(Sender: TObject) ;
var
sHTML : string;
begin
sHTML := 'GOTO' +
'<b>About Delphi Programming</b>';
WBLoadHTML(WebBrowser1,sHTML) ;
end;
but this appears to be designed for a VCL application which is incompatible with Firemonkey TWebBrowser.
How can I achieve the same thing as this code example but using the Firemonkey control?
Use WebBrowser LoadFromStrings Method.
You could implement this functionality in a DLL...detail and downloadable example here.
Another option is to consider this open-source TWebBrowserEx project. It actually will use the platform's normal web browser functionality. However, in the case of Windows it means that in your FMX project you will be using the VCL for the web browser support...which may or may not have unintended effects.
This class provide WebBrowser for All-Platform FireMonkey
Applications.
Platform => Component
Windows => IWebBrowser(IE)
OS X => WebView(Safari)
iOS => WebView
Android => WebView

Detect Chrome as browser associated with html files in Windows

We provide Flash tutorial videos that install on the local (Windows) hard disk with our application. Our app uses ShellExecute to open the html file (in whatever browser is associated with html files) in which they are embedded.
Apparently there's a bug in Chrome's more recent Flash players that fails to play local files (but files over the web are fine.)
(Frankly, I'm astonished that this bug hasn't been fixed by Google. Seems like a big one to me... but maybe not many people play Flash from locations other than the web?)
There's a work-around on the about:plugins screen in Chrome, but we can't ask our users to do that. Here's a discussion of the work-around: http://techsmith.custhelp.com/app/answers/detail/a_id/3518
I want to provide my users with an option to open our html files IE. If Chrome is their default browser, then I'd show a checkbox that says something embarrassing like "If our tutorial videos fail to play, check this box to try them in IE."
Is this XE2 code (from two years ago on SO: link) still reasonable?
if pos('CHROME', UpperCase(GetAssociation('C:\Path\File.html')) > 0 then
// Chrome is the default browser
function GetAssociation(const DocFileName: string): string;
var
FileClass: string;
Reg: TRegistry;
begin
Result := '';
Reg := TRegistry.Create(KEY_EXECUTE);
Reg.RootKey := HKEY_CLASSES_ROOT;
FileClass := '';
if Reg.OpenKeyReadOnly(ExtractFileExt(DocFileName)) then
begin
FileClass := Reg.ReadString('');
Reg.CloseKey;
end;
if FileClass <> '' then begin
if Reg.OpenKeyReadOnly(FileClass + '\Shell\Open\Command') then
begin
Result := Reg.ReadString('');
Reg.CloseKey;
end;
end;
Reg.Free;
end;
If you have an actual full path to an existing file on disk, you can use FindExecutable instead. It's easier, and doesn't require access to the registry, but it does require that an actual file exists.
Here's a console app for XE2 that demonstrates use:
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses
SysUtils, ShellAPI, Windows;
var
Buffer: array[0..MAX_PATH] of Char;
Res: Integer;
begin
FillChar(Buffer, SizeOf(Buffer), #0);
Res := FindExecutable(PChar('C:\Path\File.html'), nil, Buffer);
if Res > 32 then
Writeln('Executable is ' + Buffer)
else
WriteLn(SysErrorMessage(Res));
Readln;
end.
The method you show will work, but FindExecutable is easier (less code) and works on XP and above.

Crystal reports in Delphi 2007

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.

Image list loading fails on Delphi 6 and Vista service pack 2

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;

Resources