cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 

Community Tip - You can Bookmark boards, posts or articles that you'd like to access again easily! X

Mathcad API and c#

ptc-2540485
1-Newbie

Mathcad API and c#

Hello,

I posted this on the ptc mathcad forums before I found this place. I figured this is the right place though.

I am investigating connecting my companys Mathcad worksheets together with our Cad software. The cad part is already in place but when I started translating an example found in your helpfiles to c# regarding checking out setting/getting values from a worksheet i ran into some problems.

I added the source(below) for the test i am running. If anyone have any hints to as what I am doing wrong here or have a C# example for the MathCad API to share that would be very much appriciated.


Best regards,

Tobias Svenberg

---------- MathCad worksheet
(Trying to set a and retrieve b)

a:=
b:=a+5

---------- C# Source code
public partial class mathcadTest : Form
{

Mathcad.Application mc = new Mathcad.Application();
Mathcad.Worksheets wk;
Mathcad.Worksheet ws = new Mathcad.Worksheet();

public mathcadTest()
{
InitializeComponent();

}

private void doMathCadTest()
{
wk = mc.Worksheets;
ws = wk.Open(@"c:\temp\mathcadtest1.xmcd");
ws.SetValue("a", "10");
ws.Recalculate();
try
{
string b = ws.GetValue("b") as string;
MessageBox.Show(b);
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}

ws.Close(Mathcad.MCSaveOption.mcDiscardChanges);
System.Runtime.InteropServices.Marshal.ReleaseComObject(wk);
System.Runtime.InteropServices.Marshal.ReleaseComObject(ws);
System.Runtime.InteropServices.Marshal.ReleaseComObject(mc);
}

private void button1_Click(object sender, EventArgs e)
{
doMathCadTest();
}
}

12 REPLIES 12
PhilipOakley
5-Regular Member
(To:ptc-2540485)

The set value may be conflicting with your "a:=" which you show as unassigned.

The set value function is actioned at the top of the worksheet. I visualise that as a hidden area which has all such stuff pasted into it.

So what you get is

a:=10 (your set value, hidden at the top)
a:= (unassigned, but visible, definition)
b:=a+5 (fails because 'a' is undefined)

Note that you can never see that 'hidden area'! (I have put in an enhancement request) It's just a way of visualising.

There are a set of special variables in0 to in9 which are at the very very top of the hidden area and are pre-assigned to zero. The API set value then comes after. So you can have

in0:=0 (built in at very very top)
in0:=10 (your set value, hidden at the top)
b:=in0+5 (works, even if set value didn't!)

This allows testing.

Philip Oakley

On 2/12/2009 8:23:26 AM, philipoakley wrote:
>The set value may be
>conflicting with your "a:="
>which you show as unassigned.

Not "may be", but "will be" 🙂

If that is deleted it should work.

Richard

Hello again,

Thanks for the quick answers. I made the changes that you suggested to the worksheet.

b:= a +3


but the code

string b = ws.GetValue("b") as string;

still throws the error "the requested value was not found in the worksheet"
PhilipOakley
5-Regular Member
(To:ptc-2540485)

start with (or add) a well defined variable, such as z:=12, and see if you can get that value.

make sure you have calculated, or re-calculated, the sheet as appropriate.

Check the autocalculate setting in the worksheet

Philip Oakley
RichardJ
19-Tanzanite
(To:ptc-2540485)

Do as Philip suggests, and just start by getting the value from a simple assignment. Also try getting it as a number (since that's what it is) rather than a string, which just adds complexity.

Richard

The problem is i have to cast it to a nullable type. (int, double etc. are not nullable)

I re-did the same file with getting a simple allready set variable
b:=12;

string b = ws.GetValue("b") as string; returns null

object b = ws.GetValue("b") returns a system__comobject that contains null.

the problem as far as I found seem to be casting the retrieved value to a usable type all I get is a null value which suggest that the cast is wrong (Even the system.__comobject is null) or I get an error stating that the variable is not in the worksheet.

Has anyone tried (succesfully) getting/setting values from a worksheet using c#?
RichardJ
19-Tanzanite
(To:ptc-2540485)

What about

b:="hello world"

and then either

string b = ws.GetValue("b") as string

or

string b = ws.GetValue("b")

Richard
RichardJ
19-Tanzanite
(To:ptc-2540485)

On 2/13/2009 9:28:25 AM, TobiasS wrote:
>The problem is i have to cast
>it to a nullable type.

Why?

> (int,
>double etc. are not nullable)

They are according to MS:

http://msdn.microsoft.com/en-us/library/1t3y8s4s.aspx

Richard

Unfortunately there is more than one "int" type. "int" is a very different data type to Int32, or Int64 and depending on the requirement they are not necessarily interchangeable.

One Microsoft books describes Nulls as "evil": to be avoided if possible, but inevitably some Nulls must exist.

I'm assuming most people reading this thread know this, but historically Nulls literally meant zero (as in ascii character zero or number zero). In .Net null means an uninstantiated object. Long story short, in .Net getting a null value indicates something is afoot here � that nothing is being returned � that the variable (or perhaps even the worksheet) has not been instantiated.

I've never tried this before - I'll attempt to do up a simple c# worksheet example and if I get it going I will post it.

Philip
___________________
Correct answers don't require correct spelling.

Okay - I have the problem nutted and a soltion.

The problem is that the return value of GetValue is not typed, and therefore .Net doesn't know what it is other than some generic COM object.

So the solution is to manually cast. The solution is pasted below (also note that a should be set with an integer object rather than a string):


public partial class mathcadTest : Form
{

Mathcad.Application mc = new Mathcad.Application();
Mathcad.Worksheets wk;
Mathcad.Worksheet ws = new Mathcad.Worksheet();

public mathcadTest()
{
InitializeComponent();

}

private void doMathCadTest()
{
wk = mc.Worksheets;
ws = wk.Open(@"c:\temp\mathcadtest1.xmcd");
ws.SetValue("a", 10);
ws.Recalculate();
try
{
string b = ((Mathcad.INumericValue)(wk.GetValue("b")).Integer).ToString();
MessageBox.Show(b);
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}

ws.Close(Mathcad.MCSaveOption.mcDiscardChanges);
System.Runtime.InteropServices.Marshal.ReleaseComObject(wk);
System.Runtime.InteropServices.Marshal.ReleaseComObject(ws);
System.Runtime.InteropServices.Marshal.ReleaseComObject(mc);
}

private void button1_Click(object sender, EventArgs e)
{
doMathCadTest();
}
}



Philip
___________________
Correct answers don't require correct spelling.

FYI - a couple of tips when working with COM and C#:
1. If at all possible try to ensure the program is visible. Automating a program is much easier if you can see it.
2. Break it up into smaller steps.
3. var is useful (I'm a convert anyway), especially when dealing with COM or for loops. I think var came in with C# 3.0
4. If you hit a roadblock, and if possible, do it in VB - then try to replicate in C#. VB is the language of COM and makes it nice and easy to see what is going on.
5. Check out the object tree (double click on Mathcad in your references area). Even if it doesn't show the class of the returned object, it will still give hints. Everything in com must be exposed as a known interface/class, which is why I knew to look for a "value" interface.

Good luck.


var mc = new Mathcad.Application();
mc.Visible = true;
var wks = mc.Worksheets;
var wk = wks.Open(@"e:\mcad.xmcd");
wk.SetValue("b", 20);
var b = (Mathcad.INumericValue)(wk.GetValue("b"));
lblResults.Text = (b.Integer).ToString();


Philip
___________________
Correct answers don't require correct spelling.

Correct answers don't require correct spelling.

- Nice tag.





Ok, got it working. Thanks for all the help, our engineers will love this 😃



Here's the code, both c# and worksheet.



-------- Mathcad Worksheet -----------

/* I found that you need to leave the values you want to set through the API unassigned. Otherwise it returns what you set it to in the worksheet. Though that might be related to the bug mentioned earlier in this thread.*/



// ina and inb are the in values set from the API

a=ina

b=inb



//The answer (svar == answer in Swedish)

svar=a+b

--------------------------------





---------- #C Code -------------







public partial class mathcadTest : Form

{







public mathcadTest()

{

InitializeComponent();



}



private void doMathCadTest()

{



Mathcad.Application mc = new Mathcad.Application();

Mathcad.Worksheets wk;

Mathcad.Worksheet ws;

mc.Visible = true;



wk = mc.Worksheets;

ws = wk.Open(@"c:\temp\mathcadtest2.xmcd");



try

{

ws.SetValue("ina", 1000);

ws.SetValue("inb", 500);

ws.Recalculate();

var svar = (Mathcad.INumericValue)(ws.GetValue("svar"));

MessageBox.Show(svar.Real.ToString());

}

catch (Exception e)

{

MessageBox.Show(e.ToString());

}



ws.Close(Mathcad.MCSaveOption.mcDiscardChanges);

System.Runtime.InteropServices.Marshal.ReleaseComObject(wk);

System.Runtime.InteropServices.Marshal.ReleaseComObject(ws);

System.Runtime.InteropServices.Marshal.ReleaseComObject(mc);

}



private void button1_Click(object sender, EventArgs e)

{

doMathCadTest();

}

}





---------------------
Top Tags