We have developed an app that can import DOC/XLS files as images using LibreOffice. However, for PCs where Office is already installed, we would like to be able to use the installed MS Office. Most people are on MS Office version 2007-2010. I know that MS provide some sort of interoperability DLLs for this purpose but I haven;t seen any example of this being used with Qt.
Update - this answer looks interesting, can the same be done in Qt?
Convert Word file pages to jpg images using C#
PowerShell
It looks like you can do it with Powershell on the commandline pretty easily.
Open a QProcess, and run:
http://technet.microsoft.com/en-us/library/hh847736.aspx
powershell -Command "Import-Module MSOnline";"C:\Myscript.ps1"
(Download this script or convert it to C++ com calls.)
https://gallery.technet.microsoft.com/office/Script-to-convert-Word-f702844d
powershell -Command "Import-Module ConvertWordPocumentToPDF.psm1";"ConvertTo-OSCPDF -Path C:\path\to\document.docx"
So the end code for Qt probably could be something like:
QProcess * process = new QProcess();
// put code to pipe stdout and stderr from the QProcess to this exe's stdout, or to a TextEdit.
process->start("powershell.exe -Command \"Import-Module ConvertWordPocumentToPDF.psm1\";\"ConvertTo-OSCPDF -Path C:\\path\\to\\document.docx\"");
Com Object Access
DocumentBase.ExportAsFixedFormat Method
http://msdn.microsoft.com/en-us/library/microsoft.office.tools.word.documentbase.exportasfixedformat.aspx
public void ExportAsFixedFormat(
string outputFileName,
WdExportFormat exportFormat,
bool openAfterExport,
WdExportOptimizeFor optimizeFor,
WdExportRange range,
int from,
int to,
WdExportItem item,
bool includeDocProps,
bool keepIRM,
WdExportCreateBookmarks createBookmarks,
bool docStructureTags,
bool bitmapMissingFonts,
bool useISO19005_1,
ref Object fixedFormatExtClassPtr
)
First get an instance of a Word.Application
then get an instance of a document using wdApplication.Documents.Open
then call wdDocument.ExportAsFixedFormat, with the parameters of:
$wdExportFormat = [Microsoft.Office.Interop.Word.WdExportFormat]::wdExportFormatPDF
$OpenAfterExport = $false
$wdExportOptimizeFor = [Microsoft.Office.Interop.Word.WdExportOptimizeFor]::wdExportOptimizeForOnScreen
$wdExportItem = [Microsoft.Office.Interop.Word.WdExportItem]::wdExportDocumentContent
$IncludeDocProps = $true
$KeepIRM = $true
$wdExportCreateBookmarks = [Microsoft.Office.Interop.Word.WdExportCreateBookmarks]::wdExportCreateWordBookmarks
$DocStructureTags = $true
$BitmapMissingFonts = $true
$UseISO19005_1 = $false
$wdStartPage = 0
$wdEndPage = 0
(but formatted for c++, not powershell)
then when it is completed, release the com objects.
http://msdn.microsoft.com/en-us/library/kw65a0we.aspx
I haven't tested either method, but I have ran Com objects from a Qt project before. Hope that helps.
Related
I'm working on Visual Studio 2019 community, and I'm writing an MFC application in cpp. I want to add a functionality to the dialog box - such that when pressing a button it converts an existing xls file into pdf file. I've tried using the extension Aspose.Cells.Cpp and Aspose.PDF.Cpp with this code, but I get a lot of errors in the code of the DLL itself. I've also tried installing libHARU from here, but I didn't manage to make it work.
I've tried looking for another way to convert xls to pdf in MFC application in cpp, or another environment for creating desktop applications (which has some basic functionalities such as adding a pressing button in MFC, so I won't have to write everything from scratch with Win32 API), but I didn't find anything. Perhaps someone can explain to me how to perform this conversion in cpp so that I can use it when writing an MFC app, or could refer me to some useful information about another way of creating the application which supports this type of conversions?
You said in your comments to me that you can assume the user has Excel installed on his machine. If so, then you can use Excel's automation object model to manipulate Excel. You could do stuff like #import the type library and stuff...maybe that would make prettier C++. My experience, however, with driving Office apps is to stick more with just raw dispatch pointers. I've had less go wrong that way. This probably needs some more error checking and stuff, but that's up to you.
... and a big caveat. This is for an interactive app...which I halfway assume since you are using the MFC topic. With a service, Microsoft does not recommend you drive their Office applications in this manner. I tested this on one .xlsx file and it worked. Assume it will work for .xls as well. For other formats, you might need to use different import functions.
void ConvertFile(LPCWSTR lpszFileIn, LPCWSTR lpszFileOut)
{
CComDispatchDriver excel;
if (SUCCEEDED(excel.CoCreateInstance(_T("Excel.Application"), NULL, CLSCTX_LOCAL_SERVER)))
{
_variant_t vWorkbooks;
if (SUCCEEDED(excel.GetPropertyByName(L"Workbooks", &vWorkbooks)))
{
CComDispatchDriver workbooks(vWorkbooks.pdispVal);
_variant_t vWorksheet;
if (SUCCEEDED(workbooks.Invoke1(L"Open", &_variant_t(lpszFileIn), &vWorksheet)))
{
CComDispatchDriver worksheet(vWorksheet.pdispVal);
UINT xlTypePdf = 0;
HRESULT hr = worksheet.Invoke2(L"ExportAsFixedFOrmat", &_variant_t(xlTypePdf), &_variant_t(lpszFileOut), NULL);
if (FAILED(hr))
{
_com_error err(hr);
AfxMessageBox(err.ErrorMessage());
}
}
}
excel.Invoke0(L"Quit", NULL);
}
}
I'll give a solution, but this one doesn't use c++, just command line and LibreOffice app:
Use command line Libre Office tool: --convert-to
--convert-to output_file_extension[:output_filter_name] [--outdir output_dir] files
Batch convert files. If --outdir is not specified, then current working directory is used as output_dir.
Eg. --convert-to pdf *.doc
--convert-to pdf:writer_pdf_Export --outdir /home/user *.doc
More details about how to use this command you'll find here: https://help.libreoffice.org/Common/Starting_the_Software_With_Parameters
Later edit: Here is a sample of how to implement the above solution in a C++/MFC code:
STARTUPINFO si = { 0 };
si.cb = sizeof(si);
PROCESS_INFORMATION pi = { 0 };
sCommand.Format(_T("C:\\WINDOWS\\System32\\cmd.exe /c
C:\\LibreOffice\\program\\swriter.exe --convert-to pdf -outdir
c:\\temp\\ c:\\temp\\MyFile.doc"));
::CreateProcess(0, sCommand, 0, 0, TRUE, CREATE_NO_WINDOW, 0, 0, &si, &pi);
In my application (Windows 10 VC2017) i enabled the possibility to write and execute scripts using google v8 and v8pp.
v8pp calls a script like this:
v8::Local<v8::Value> context::run_script(std::string const& source, std::string const& filename)
{
v8::EscapableHandleScope scope(isolate_);
v8::Local<v8::Context> context = isolate_->GetCurrentContext();
v8::ScriptOrigin origin(to_v8(isolate_, filename));
v8::Local<v8::Script> script;
bool const is_valid = v8::Script::Compile(context,
to_v8(isolate_, source), &origin).ToLocal(&script);
v8::Local<v8::Value> result;
if (!script.IsEmpty())
{
auto res1 = script->Run(context); //
if(! res1.IsEmpty())
result = res1.ToLocalChecked();
}
return scope.Escape(result);
}
How can i attach a debugger (chrome debug) to my code?
I found googles description at https://v8.dev/docs/inspector -
But this leaves some things blank and consists mostly of js code?
And i found the implementation for v8toolkit at https://github.com/xaxxon/v8toolkit/blob/master/src/debugger.cpp. But this seems to run not for windows.
What is a easy way to attach chrome debug to js code? The code is typically not a file but rather is stored in a data base and then stored in a std::string.
I finally got done a windows version of v8inspector that works well with my stand alone windows application with integrated v8.
I made a own fork including descriptions where to find/build the required 3rd party libraries (or where to find prebuilds). I also did a number of changes/additions:
https://github.com/StefanWoe/v8inspector
In the meanwhile this has also been merged into the parent project:
https://github.com/hsharsha/v8inspector
EDIT:
In the meanwhile ive been pointed to another implementation built with boost::beast and no other dependencies. Much simpler and more robust etc.:
https://github.com/ahmadov/v8_inspector_example
I want to list all application which had been installed by reading uninstall registry file from HKEY_CURRENT_USER. But look like it can't be done by using QSettings, for some security reason ( i guess ).
QSettings maya("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall
People suggest to use WinAPI to accomplish this (at least, on Window platform)
Can somebody guide me how to add and use this lib please?
Thank
In order to get the list of all sub items under the "Uninstall" one in the Windows registry you need to use QSettings::childGroups() function, i.e:
QSettings m("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
QSettings::NativeFormat);
QStringList ak = m.childGroups();
This will return the list of all installed applications.
UPDATE:
After getting the list of installed applications one can read the installation details. There are two ways for doing that. For example to read the "UinstallPath" key for "Autodesk Maya 2014" application:
m.beginGroup("Autodesk Maya 2014");
QString path = m.value("UninstallPath").toString();
m.endGroup();
or simply:
QString path = m.value("Autodesk Maya 2014/UninstallPath").toString();
We are a Windows shop using Powershell extensively.We also have a Spacewalk that I would like to poll some data from as part of the existing Powershell script. Spacewalk API is exposed via XMLRPC.
I have spent some time searching for examples on how this can be done but the information is really scarce. The closest I could get was this link ( no longer available)
https://web.archive.org/web/20080202045713/http://thepowershellguy.com/blogs/posh/archive/2008/01/31/powershell-and-xmlrpc-posh-challenge-part-12.aspx
Lack of examples makes me think that I am looking in the wrong direction. I know about new-webserviceproxy and I used it for quering Sharepoint but I don't see anyone using it for XMLRPC calls.
It is trivial to write the call in Perl or Python but this is not what I need in this specific case...
Am I going the wrong way here?
Just implemented this myself, so I thought I'd pass it along.
You can actually download the DLL instead of compiling the source yourself - I found the DLL by using NuGet, but some say you can get it from the zip.
I decided to implement the interfaces in C# code within powershell to maximize portability / ease of development. If you want, you can compile the C# code as a DLL and load that using powershell, but you'll have to go back and recompile every time you want to make a change to the C# code. Here, powershell recompiles for you on the fly. (The only downside is that if you use the native windows powershell IDE, you have to close and reopen to clear your session every time you make a change to the C# code)
Here's an example of the OpenSubtitles API using XML-RPC.NET and powershell (not the cleanest code, but hopefully illustrates the XML-RPC.net usage):
$source = #'
namespace OpenSubtitlesAPI
{
using CookComputing.XmlRpc;
[XmlRpcUrl("http://api.opensubtitles.org/xml-rpc")]
public interface IOpenSubtitles : IXmlRpcProxy
{
[XmlRpcMethod("LogIn")]
XmlRpcStruct LogIn(string username, string password, string language, string useragent);
[XmlRpcMethod("LogOut")]
XmlRpcStruct LogOut(string token);
[XmlRpcMethod("SearchSubtitles")]
XmlRpcStruct SearchSubtitles(string token, XmlRpcStruct[] queries);
[XmlRpcMethod("SearchSubtitles")]
XmlRpcStruct SearchSubtitles(string token, XmlRpcStruct[] queries, int limit);
}
public class ProxyFactory
{
public static IOpenSubtitles CreateProxy()
{
return XmlRpcProxyGen.Create<IOpenSubtitles>();
}
}
}
'#
# Load XML-RPC.NET and custom interfaces
if ([Type]::GetType("OpenSubtitlesAPI.ProxyFactory") -eq $null)
{
[Reflection.Assembly]::LoadFile("C:\path\to\CookComputing.XmlRpcV2.dll") | Out-Null
$dynamicAssembly = Add-Type -TypeDefinition $source -ReferencedAssemblies ("C:\path\to\CookComputing.XmlRpcV2.dll")
}
# Set up proxy
$proxy = [OpenSubtitlesAPI.ProxyFactory]::CreateProxy()
$proxy.UserAgent = "user agent"
$proxy.EnableCompression = $true
# Log in
$LogInResponse = $proxy.LogIn("user name", "password", "language", "user agent")
# Build query
$query = New-Object CookComputing.XmlRpc.XmlRpcStruct
$query.Add("moviehash", "movie hash")
$query.Add("moviebytesize", "movie size")
$query.Add("sublanguageid", "language")
$queries = #($query)
# Search
$SearchResponse = $proxy.SearchSubtitles($LogInResponse.token, $queries)
# Log out
$LogOutResponse = $proxy.LogOut($LogInResponse.token)
My response is a bit delayed to the initial question, but hopefully this helps someone out there.
Have you looked at XML-RPC.NET? You would have to create a XmlRpcProxyGen class in C# that implements IXmlRpcProxy but once you've done that, you should be able to load that .NET assembly and use the proxy class from PowerShell.
I want to develop a small tool which for open XML file and launch Excel automatically.
The benefit for user who could save the excel file to .xls format very conveniently.
My Dev IDE: Windows XP pro & Visual Studio 2005.
The tool will running at Windows 2000 & Excel 2000. and there is no .net framework installed.
That means i can't code with C#. My choice is C++.
Oneliner:
int main() {
system("Start Excel test.xml");
}
If I recall correctly you want to open an excel file and then auto launch xml editor?
A way is to add a option the the contect menu when rightclicking on the xls file.
Use register for this:
HKEY_CLASSES_ROOT.xls\shell\
create a key (Default) and value something like "Open excel and xml editor"
create a folder "command" and a key (Default) with value "path to your exe" "%L" in that folder.
Then in your app catch the param (which holds the xls)
and then do something like this:
system(<var holding the xls name>);
system(<path to xml editor>):
You could use ShellExecute. It will automatically start program which associated with certain extension, or you could select program manually.
In C#
OpenXML in MSDN - http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.workbooks.openxml(v=office.11).aspx
using Excel = Microsoft.Office.Interop.Excel;
string workbookPath= #"C:\temp\Results_2013Apr02_110133_6692.xml";
this.lblResultFile.Text = string.Format(#" File:{0}",workbookPath);
if (File.Exists(workbookPath))
{
Excel.Application excelApp = new Excel.Application();
excelApp.Visible = true;
Excel.Workbook excelWorkbook = excelApp.Workbooks.OpenXML(workbookPath, Type.Missing, Excel.XlXmlLoadOption.xlXmlLoadPromptUser);
}
else
{
MessageBox.Show(String.Format("File:{0} does not exists", workbookPath));
}