Delphi 7 and Excel 2007 Open File Error - delphi

I am having difficulty opening a EXCEL 2007 in Delphi 7 It works for Office 2003 and below but the wonderful people at microsoft have sent an update or something and the delphi app fell over just earlier this month.
oE := GetActiveOleObject('Excel.Application');
oE.Workbooks.Open(Filename:=sFilename, UpdateLinks:=false, ReadOnly:=true); //Error
I get the following error:
'c:\Temp\Book1.xls' could not be
found. Check the spelling of the file
name, and verify that the file
location is correct.'#$A#$A'If you are
trying to open the file from your list
of most recently used files, make sure
that the file has not been renamed,
moved, or deleted'
Yet if I run the same command in VBA there is no problem.

I know this sounds stupid, but have you manually confirmed that the file exists at that location?
What exactly is the contents of sFileName, is it the full path or only the filename? When it is only the filename, maybe Excel can't find it because its current working directory is something else. If you are only passing the filename, try the full path instead.

the full code for the lookers :
uses ComObj; ..
procdure startExcel;
var
oE:Variant;
begin
try
oE := GetActiveOleObject('Excel.Application');
except
oE := CreateOleObject('Excel.Application');
end;
oE.Workbooks.Open(filename, false, false);
oE.Visible := True;
end;
source

Related

Opening rtf file in Delphi generates error

I am loading a RichEdit file using the following code:
RichEdit1.Lines.LoadFromFile('xxx.rtf');
This works well. However when I use the TOpenDialog like this:
with DlgOpen do if Execute then RichEdit1.Lines.LoadFromFile(FileName);
I run into a problem. The file loads alright but leaves the following error message on the desktop:
I am using Delphi 2010. The rtf file was generated using Microsoft Word 2007 and I am running Win10.
How can I get rid of the error message?
If you can't prevent the previewer to lock the file you want to read, I would work around it by not loading directly that file but a copy of it.
uses IOUtils;
....
....
var TempFile: string;
....
if DlgOpen.Execute then
begin
TempFile := IncludeTrailingPathDelimiter(TPath.GetTempPath) + 'Temp.rtf';
CopyFile(PChar(DlgOpen.FileName), PChar(TempFile), False);
RichEdit1.Lines.LoadFromFile(TempFile);
DeleteFile(TempFile);
end;

Delphi - Using OLE causes error in Word

Delphi XE6. I have an application for text snippets, which are stored in a local Database (ABS DB). Some snippets may be straight text, others may include formatting. If the snippets include formatting, the snippets are MS Word format.
The user can view the snippets in two ways, inside my app, or by calling MS-Word, and having the snippet loaded there automatically, - IT IS THE SAME SNIPPET ..
Issue: If the snippet is loaded into a TOLEContainer in my app, it displays fine without a problem... If the snippet gets spawned off into MSWord, I get an error...
"We're sorry. We can't open because we found a problem with its contents." I click on OK, and then get "Word found unreadable content in . Do you want to recover the contents of this document?..." I clik OK, and everything displays fine.
My general processing flow for the "spawn off MS WORD" is...
// FN is a temp file name
FileStream := TFileStream.Create(FN, fmCreate);
BlobStream := dm_text.tEntries.CreateBlobStream(dm_text.tEntries.FieldByName('ANSWER_FMT'), bmRead);
FileStream.CopyFrom(BlobStream, BlobStream.Size);
BlobStream.Free;
FileStream.Free;
// Now open default association, which will be Word
ShellExecute(Handle, 'open', PWideChar(FN), nil, nil, SW_SHOWNORMAL);
This flow is nearly identical for the In place viewing... other than a few commands for the TOleContainer.
OleWord.Enabled := True;
FileStream := TFileStream.Create(FN, fmCreate);
BlobStream := tEntries.CreateBlobStream(tEntries.FieldByName('ANSWER_FMT'), bmRead);
FileStream.CopyFrom(BlobStream, BlobStream.Size);
BlobStream.Free;
FileStream.Free;
OleWord.LoadFromFile(FN);
OleWord.DoVerb(ovInPlaceActivate);
Any ideas why this is happening? This happens on MULTIPLE versions of MSWord.
ADDITIONAL INFO:
Both routines look at the same data, pulled from the exact same row/column in my DB. What I do is create a TEMP file, and then load either via TOleContainer, which loads it fine, or via ShellExecute, which gives an error. However, if I manually load the TEMP file for the OLE Container into MSWord, I get the same error.
So - possibilities...
1). My data is corrupted, i.e. how I save it is wrong...but Word can correct it.
2). I have a setting somehow so that OLEContainer doesn't show the error but Word does.
It is because when using OleContainer.SaveToFile or SaveAsDocument, you are not creating a docx file, but an OleObject containing a docx file. When using OleContainer.SaveToFile with UseOldStreamFormat = True, there is even a Delphi specific header added. Word fortunatly detects this and gives you the option to restore the file.
If you want a valid word-document, then activate the OleContainer (OleContainer.DoVerb(ovPrimary) and then save the document via Word itself (OleContainer.OleObject.SaveAs(MyFileName, wdFormatDocument, EmptyParam, EmptyParam, False).
After that you can store the resulting file in your database.

Checking if the file is in use and by which application?

Trying to use the below mentioned approach to get more details about the locked file.
Is file in use
function GetFileInUseInfo(const FileName : WideString) : IFileIsInUse;
var
ROT : IRunningObjectTable;
mFile, enumIndex, Prefix : IMoniker;
enumMoniker : IEnumMoniker;
MonikerType : LongInt;
unkInt : IInterface;
begin
result := nil;
OleCheck(GetRunningObjectTable(0, ROT));
OleCheck(CreateFileMoniker(PWideChar(FileName), mFile));
OleCheck(ROT.EnumRunning(enumMoniker));
while (enumMoniker.Next(1, enumIndex, nil) = S_OK) do
begin
OleCheck(enumIndex.IsSystemMoniker(MonikerType));
if MonikerType = MKSYS_FILEMONIKER then
begin
if Succeeded(mFile.CommonPrefixWith(enumIndex, Prefix)) and
(mFile.IsEqual(Prefix) = S_OK) then
begin
if Succeeded(ROT.GetObject(enumIndex, unkInt)) then
begin
if Succeeded(unkInt.QueryInterface(IID_IFileIsInUse, result)) then
begin
result := unkInt as IFileIsInUse;
exit;
end;
end;
end;
end;
end;
end;
But the call to
unkInt.QueryInterface(IID_IFileIsInUse, result)
always returns E_NOINTERFACE.
Platform: Windows 7 32 bit-OS, opening word files and .msg files.
Checked opening files from the explorer and trying to delete. It shows proper details about the application in which the file is opened. In my application, I am try to display the information about application in which the file is opened. But when trying to cast the pointer to IFileIsInUse interface, QueryInterface calls fails with return code E_NOINTERFACE which means the object in ROT does not implement IFileIsInUse. AFASIK, MS Office files implements IFileIsInUse
Any idea what is wrong here?
In fact your code works fine. The problem is that the programs you are testing against really do not implement IFileIsInUse. When the system returns E_NOINTERFACE it is accurate. The interface is not implemented.
I tested this with the File Is In Use Sample from the SDK. Files that are added to the ROT by that application, which does implement IFileIsInUse, were picked up by your code. On the other hand, files opened by Acrobat 8 and Word 2010 were not.
The conclusion that I draw from this is that IFileIsInUse is a fine idea in principle, but not much use if applications don't support it. And it appears that there are major applications that do not.
It is clear that you will need to use one or more of the other mechanisms to detect which application has a file locked when you find that IFileIsInUse is not implemented.
SysInternals Process Explorer worked for me to delete a locked .msg file that was causing system problems like locking up the desktop.
Run Process Explorer, use the Find menu,
enter the full path file name,
hit Search.
For deleting a locked file, I opened a cmd window and tried to del the locked file, but the delete hung on the lock.
Then I used Process Explorer to restart the process holding the lock - Explorer.exe.
The del then completed successfully.

CopyFile docx makes hidden conversion to doc

i got a Delphi 7 program which has to copy a docx file. I'm using the Windows API CopyFile function. The problem is that this function seems to make a hidden conversion to the older doc format.
First thing: the file size increases after the copy.
Second: When opening the file in Office 2007 i got an error message stating that: Check your permissions to the document or disk, check free disk space.
And than the strange thing: if i change in TotalCommander the extension of the copied file from docx to doc it opens normally. So it seems to make a hidden conversion dont know why.
Tested on two different computers. Both Win XP Prof SP3, Office 2007 Prof Plus SP2
Any ideas?
Function body is below:
function TDlgNowySzablon.PobierzPlikNaDoc() : string;
var
openDlg : TOpenDialog;
begin
Result:='';
openDlg:=TOpenDialog.Create(self);
openDlg.Filter:='Dokumenty Microsoft Word (*.doc;*docx)|*.doc;*.docx';
if openDlg.Execute then begin
Result := IObsSzab.GetTempFullFileName( ExtractFileExt(openDlg.FileName) );
if not CopyFile(PChar(openDlg.FileName),PChar(Result),true) then begin
Result:='';
end;
end;
openDlg.Free;
end;
Try changing your code as follows:
Result := IObsSzab.GetTempFullFileName('.tmp');
Result := ChangeFileExt(Result, ExtractFileExt(openDlg.FileName));
I think your GetTempFullFileName function is truncating .docx to .doc. It's all guesswork though!
The CopyFile function does not modify the contents of the file.

Open an ANSI file and Save a a Unicode file using Delphi

For some reason, lately the *.UDL files on many of my client systems are no longer compatible as they were once saved as ANSI files, which is no longer compatible with the expected UNICODE file format. The end result is an error dialog which states "the file is not a valid compound file".
What is the easiest way to programatically open these files and save as a unicode file? I know I can do this by opening each one in notepad and then saving as the same file but with the "unicode" selected in the encoding section of the save as dialog, but I need to do this in the program to cut down on support calls.
This problem is very easy to duplicate, just create a *.txt file in a directory, rename it to *.UDL, then edit it using the microsoft editor. Then open it in notepad and save as the file as an ANSI encoded file. Try to open the udl from the udl editor and it will tell you its corrupt. then save it (using notepad) as a Unicode encoded file and it will open again properly.
Ok, using delphi 2009, I was able to come up with the following code which appears to work, but is it the proper way of doing this conversion?
var
sl : TStrings;
FileName : string;
begin
FileName := fServerDir+'configuration\hdconfig4.udl';
sl := TStringList.Create;
try
sl.LoadFromFile(FileName, TEncoding.Default);
sl.SaveToFile(FileName, TEncoding.Unicode);
finally
sl.Free;
end;
end;
This is very simple to do with my TGpTextFile unit. I'll put together a short sample and post it here.
It should also be very simple with the new Delphi 2009 - are you maybe using it?
EDIT: This his how you can do it using my stuff in pre-2009 Delphis.
var
strAnsi : TGpTextFile;
strUnicode: TGpTextFile;
begin
strAnsi := TGpTextFile.Create('c:\0\test.udl');
try
strAnsi.Reset; // you can also specify non-default 8-bit codepage here
strUnicode := TGpTextFile.Create('c:\0\test-out.udl');
try
strUnicode.Rewrite([cfUnicode]);
while not strAnsi.Eof do
strUnicode.Writeln(strAnsi.Readln);
finally FreeAndNil(strUnicode); end;
finally FreeAndNil(strAnsi); end;
end;
License: The code fragment above belongs to public domain. Use it anyway you like.

Resources