I got some help here last March with writing a program to read and modify cells in a Calc spreadsheet, and with the help I received was successful in writing several very useful programs. Now I’m trying to write a program to insert images into a spreadsheet. I’ve got a test program that runs but throws an exception when trying to Add the XShape to XShapes and does not insert a visible image.
Here is the program:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Threading;
using unoidl.com.sun.star.awt;
using unoidl.com.sun.star.lang;
using unoidl.com.sun.star.uno;
using unoidl.com.sun.star.bridge;
using unoidl.com.sun.star.frame;
using unoidl.com.sun.star.sheet;
using unoidl.com.sun.star.beans;
using unoidl.com.sun.star.container;
using unoidl.com.sun.star.drawing;
using unoidl.com.sun.star.table;
using unoidl.com.sun.star.text;
using unoidl.com.sun.star.util;
// addpic
// add picture to spreadsheet - debug version
class OpenOfficeApp {
[STAThread]
static void Main(string[] args) {
bool lreadonly;
string pqfile;
string pqpic;
XNameContainer XNC;
pqfile = "file:///D:/Documents/NSexeye/ODS%20File%20Access/"+
"addpix/addpic.ods";
Console.WriteLine("Using: "+pqfile);
lreadonly = false;
XComponentContext XCC = uno.util.Bootstrap.bootstrap();
XMultiComponentFactory XMCF =
(XMultiComponentFactory)XCC.getServiceManager();
XMultiServiceFactory XMSF1 = (XMultiServiceFactory)XCC.getServiceManager();
XComponentLoader XCL =
(XComponentLoader)XMSF1.createInstance("com.sun.star.frame.Desktop");
// open the spreadsheet
PropertyValue[] pPV = new PropertyValue[2];
pPV[0] = new PropertyValue();
pPV[0].Name = "Hidden";
pPV[0].Value = new uno.Any(true);
pPV[1] = new PropertyValue();
pPV[1].Name = "ReadOnly";
if (lreadonly) pPV[1].Value = new uno.Any(true);
else pPV[1].Value = new uno.Any(false);
XComponent XCo = XCL.loadComponentFromURL(pqfile,"_blank",0,pPV);
XSpreadsheets XSSs = ((XSpreadsheetDocument)XCo).getSheets();
XNameAccess XNA = (XNameAccess)XSSs;
XSpreadsheet XSS = (XSpreadsheet)XNA.getByName("Sheet1").Value;
XCellRange XCR = (XCellRange)XSS;
// get size and position of cell
// this is an attempt to read the Size from the cell...
XCell XC = (XCell)XCR.getCellRangeByName("A1");
XPropertySet XPSc = (XPropertySet)XC;
uno.Any uAsz = XPSc.getPropertyValue("Size");
// ...but I can't figure out how to cast the uno.Any to an awt.Size...
/* unoidl.com.sun.star.awt.Size Sc = (unoidl.com.sun.star.awt.Size)uAsz; */
// what I want but don't know how to do:
/* new unoidl.com.sun.star.awt.Size Sc = XC.getSize(); */
/* new unoidl.com.sun.star.awt.Point Pc = XC.getPosition(); */
// just use constants for now...
unoidl.com.sun.star.awt.Size Sc =
new unoidl.com.sun.star.awt.Size(2541,2541); //1" x 1"
unoidl.com.sun.star.awt.Point Pc =
new unoidl.com.sun.star.awt.Point(100,100); //guess
// add a picture to a cell
pqpic = "addpic";
Console.WriteLine("Inserting picture: "+pqpic+".jpg");
XMultiServiceFactory XMSF2 = (XMultiServiceFactory)XCo;
// create bitmap container containing image
XNC = (XNameContainer)
XMSF2.createInstance("com.sun.star.drawing.BitmapTable");
if (XNC == null) Console.WriteLine("XNC is null");
XNC.insertByName(pqpic,new uno.Any(pqpic+".jpg"));
// get internal URL of image
// this gives a NoSuchElementException -- I don't know why:
/* string pqintURL = XNC.getByName(pqpic).Value.ToString(); */
string pqintURL = "???";
// create graphic shape service
Object GOS = null;
GOS = XMSF2.createInstance("com.sun.star.drawing.GraphicObjectShape");
XShape XS = (XShape)GOS;
if (XS == null) {
Console.WriteLine("XS is null");
return;
}
// set image internal URL, size and position
XPropertySet XPS = (XPropertySet)XS;
XPS.setPropertyValue("GraphicURL",new uno.Any(pqintURL));
XS.setSize(Sc);
XS.setPosition(Pc);
// insert the image
XDrawPageSupplier XDPS = (XDrawPageSupplier)XSS;
XDrawPage XDP = XDPS.getDrawPage();
if (XDP == null) {
Console.WriteLine("XDP is null");
return;
}
XShapes XSs = (XShapes)XDP;
try {
XSs.add(XS);
}
catch (System.Exception E) {
Console.WriteLine("Add: "+E);
}
Console.WriteLine("Image "+pqpic+".jpg inserted as "+pqintURL);
XModifiable XM = (XModifiable)XCo;
XM.setModified(true);
XCloseable XCl = (XCloseable)XCo;
XCl.close(true);
XDesktop XD = (XDesktop)XCL;
if (XD != null) XD.terminate();
}
}
(Sorry it’s long; I’ve included the whole program because it annoys me when code snippets use things that aren’t defined or do not show the required includes.)
If I run this I get the following output (stdout and stderr combined:
Using: file:///D:/Documents/NSexeye/ODS%20File%20Access/addpix/addpic.ods
Inserting picture: addpic.jpg
Add: unoidl.com.sun.star.lang.IllegalArgumentException
Server stack trace:
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at unoidl.com.sun.star.drawing.XShapes.add(XShape xShape)
at OpenOfficeApp.Main(String[] args) in D:\Documents\NSexeye\ODS file access\addpix\addpic.cs:line 117
Image addpic.jpg inserted as ???
The main problem I am trying to solve is the exception when trying to do the Add. I have several other problems, some of which are described in comments in the source. If you can see a solution to any of them I would appreciate it if you could tell me, but they are secondary and I’ll get to them separately if needed.
I’ve attached the simple spreadsheet that I’m trying to run this program on:
addpic.ods (6.9 KB)
You should be able to compile and run this program. I work with the command-line compiler instead of an IDE because it suits my style, but I think you could just paste the code into Visual Studio.
My sample program consists of bits of code I’ve cobbled together from many samples and gotten to work, plus new code I’ve added for this add-image task. I don’t know if any of it is the correct way to do things, and errors may be hidden in any of it, any one of which could be contributing to it not working.
A little relevant information about me: I have a little bit of autism and think a little differently that most people. I have trouble grasping abstract complex things, which the LO SDK is chock full off. Recommendations like “learn the object model” won’t help me. I am, however, very good at coding and understanding what code does, which for complex stuff like this means lots of looking things up.
I’m also having difficulty learning/understanding MRI, because doing so seems to require knowing and understanding a lot of hidden stuff. I’ve spent many hours playing with it and reading the documentation for it, but I still feel that it could help me if I could get my head around it.
What I hope to achieve with this and related posts is, of course, getting my program (which will be much more complex than my sample) working, but also leaving behind instructions and sample code for doing what I am trying to do, which it seems that many other people want to do as well. I’ve found several examples of others trying to do this, but nothing complete and nothing that I can get to work.
I do understand what’s happening with inserting an image: the image is a Shape containing a Bitmap that is placed on an “overlay” of the spreadsheet called a DrawPage, and that there is little linkage between the overlay containing the image and the spreadsheet. I do have many questions about this, which I’ll get to in due time…
If you’ve had the patience to read through to the end of this very long initial post, I’m very grateful. And I’ll be especially grateful if you can help!
Thank you!