Autodesk Inventor API Adventures – Friday

(Sometimes as a developer you get to be a super hero and overcome incredible odds. Of course, it helps if you have the skills to pull off magic – in this week-long story we paint a tongue-in-cheek picture of one of those situations. Check out the beginning of the week posts first: Monday, Tuesday, Wednesday, Thursday, and continue below for this story’s conclusion)

Finally! Friday! The day you have been waiting for. As you approach your building after parking in your new parking space, the boss greets you at the door and says “I can’t wait to see all the progress you have made” and your quick response was “I can’t wait to show you how far I’ve gotten”. With a look of extreme puzzlement, he glares at you with laser beam eyes that could destroy a super collider. You both ride up the elevator without saying a word. Your boss, Sam, doesn’t take his eyes off you; however, when the elevator door opens, he says just under his breath “By the way, management moved you to a new spot.” You look around, but fail to see your name on any of the cubicles, so you decide to just go to where you always were. As you approach your cubical, you hear typing coming from there and wonder what is going on. You glance in and notice a new face sitting there. You question him on your move and he points to the southwest corner of the building. You turn and start walking and notice the maintenance man spelling your name out on the door. You slowly approach and as he steps aside, you go in and notice the new mahogany desk. You set your coffee down and look around only to notice the skyline out the windows. Yes, you have windows. With a huge grin you sit down in your chair and run your hands over the glossiness that has become yours. Within seconds, Sam sticks his head in and says “3 o’clock sound good to you?” You think about it for a second and reply with “How about noon? I have an appointment this afternoon.” Sam seems startled but agrees and closes the door. As you turn on your computer, Heidi, from the marketing department, walks in and delivers a doughnut, the exact one you like. How did she know? Things are looking better and better, every day.

You gaze out the window one more time, take a bite of the doughnut, and start programming. With only a few things left, you decide that once you are done, you could automate this system a little more, just to show the boss what’s going on. You modify the dialog some and come up with this.

Final Dialog

Final Dialog

You think to yourself, nothing is worth anything, if you can’t save it. The specifications read that you need to save the IDW, export a DXF, take a snapshot (in jpg format) and generate a PDF. After linking the button events, you begin the final stages of automation.

To ensure your code is running and to make things easier as most of these techniques are shared, you create some helper functions. These helper functions are wrapped into a few methods that can fetch your final file destination and show a modal dialog (and hide it) while saving is being executed. Here are some member variables you declare to support your animation and saving methods.

private readonly string EXPORT_FILENAME = "MyExport";
private readonly string IDW_SAVE_FILENAME = "MyIDW";
private readonly string FILE_PATH = @"c:\Data";
private Exporting m_exportDialog = null;
private bool m_automating = false;

The helper functions are basic, but here they are.

private string GetFullSavePathAndDeleteIfExists(string fileName, string extension)
{
	string fullFileName = System.IO.Path.Combine(FILE_PATH, fileName);
	fullFileName = System.IO.Path.ChangeExtension(fullFileName, extension);

	if (System.IO.File.Exists(fullFileName))
	{
		System.IO.File.Delete(fullFileName);
	}

	return fullFileName;
}
private void ShowExportDialog(string title, string message, bool isFile)
{
	System.Diagnostics.Debug.Assert(null == m_exportDialog, "Lingering message dialog");

	if (isFile)
	{
		message = String.Format("Generating file: {0}", message);
	}

	m_exportDialog = new Exporting(title, message);
	m_exportDialog.Show();
}

private void HideExportDialog(string title, string status)
{
	if (!m_automating)
	{
		MessageBox.Show(status, title, MessageBoxButtons.OK, MessageBoxIcon.Information);
		return;
	}

	System.Diagnostics.Debug.Assert(null != m_exportDialog, "NO message dialog to close");
	m_exportDialog.Close();
	m_exportDialog = null;
}

That should make things easier! Saving the IDW is a quick call; let’s get that one out of the way. After getting the destination file location, you initially just call the .SaveAs() method. When you did, you realized that a dialog popped up and wanted you to confirm various object saving. Since you do not want to modify the original template, you cycle through the referenced documents and set their dirty flags to false. You run it again and realize the dialog still comes up. There is only one solution for this. Let’s just hide that with the SilentOperation flag on application. Presto! That worked great! Here is what you came up with.

private void btnSave_Click(object sender, EventArgs e)
{
	string fullFileName = GetFullSavePathAndDeleteIfExists(IDW_SAVE_FILENAME, "idw");
	ShowExportDialog("Saving IDW", fullFileName, true);

	foreach (DocumentDescriptor docDesc in m_idw.ReferencedDocumentDescriptors)
	{
		docDesc.ReferencedDocument.Dirty = false;
	}
	m_idw.Dirty = false;

	m_application.SilentOperation = true;
	m_idw.SaveAs(fullFileName, true);
	m_application.SilentOperation = false;
	HideExportDialog("IDW Saved", "Success");
}

If you thought that was easy, let’s try saving the picture next…

private void btnSaveIDWasJPG_Click(object sender, EventArgs e)
{
	string fullFileName = GetFullSavePathAndDeleteIfExists(IDW_SAVE_FILENAME, "jpg");
	ShowExportDialog("Creating JPG", fullFileName, true);
	m_idw.SaveAs(fullFileName, true);
	HideExportDialog("JPG Created", "Success");
}

Yup, that was all. This is going a lot quicker than expected. You might have to move the meeting up some. You decide to call your boss, Sam, and see if he can move the meeting up to 10:30 am, as you are projecting to be done early. He chuckles and says sure and hangs up. His tone reflected that he doubts you, but we will see who has the last laugh.

After some research, you realize that saving to a PDF or a DXF takes the use of a translator addin that is supplied with Inventor. After locating the Addin ID, you set the options and make the calls to perform the translation. For translations, you should set what you would like to see on each page, and to do this, you will need to setup an options list and fill it with options for each sheet. Here are the methods I created to help with the translation call options.

private NameValueMap GetSheetOptions()
{
	NameValueMap oSheets = m_application.TransientObjects.CreateNameValueMap();
	foreach (Sheet sheet in m_idw.Sheets)
	{
		NameValueMap s1 = m_application.TransientObjects.CreateNameValueMap();
		s1.Add("Name", sheet.Name);
		s1.Add("3DModel", false);
		oSheets.Add(string.Format("Sheet{0}", oSheets.Count + 1), s1);
	}

	return oSheets;
}

You are so excited that this is coming together so nicely. Again, you look around and can’t believe last week you were sitting in the cube next to “John the loud typer”. You just realize something, you can play the radio in here and not annoy anybody. You load up your favorite streaming site and choose some 60’s rock and roll to get you fired up. Next, let’s get those PDF and DXF files generated.
Both translators are almost identical, but we are going to keep most of their functionality separate just in case you want to specifically change something in one later and not affect the other.

private void btnExportPDF_Click(object sender, EventArgs e)
{
	string fullFileName = GetFullSavePathAndDeleteIfExists(EXPORT_FILENAME, "pdf");

	ShowExportDialog("Exporting PDF", fullFileName, true);

	try
	{
		TranslatorAddIn oPDFTrans = (TranslatorAddIn)m_application.ApplicationAddIns.ItemById["{0AC6FD96-2F4D-42CE-8BE0-8AEA580399E4}"];
		if (null == oPDFTrans)
		{
			MessageBox.Show("Could not load PDF Translator addin", "Export Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
			return;
		}

		TranslationContext oContext = m_application.TransientObjects.CreateTranslationContext();
		NameValueMap oOptions = m_application.TransientObjects.CreateNameValueMap();
		if (oPDFTrans.HasSaveCopyAsOptions[m_idw, oContext, oOptions])
		{
			oContext.Type = IOMechanismEnum.kFileBrowseIOMechanism;
			DataMedium oData = m_application.TransientObjects.CreateDataMedium();

			oOptions.Value["Sheet_Range"] = PrintRangeEnum.kPrintAllSheets;
			oOptions.Value["Vector_Resolution"] = 300;

			oOptions.Value["All_Color_AS_Black"] = false;
			oOptions.Value["Sheets"] = GetSheetOptions();

			oData.FileName = fullFileName;
			oPDFTrans.SaveCopyAs(m_idw, oContext, oOptions, oData);

			HideExportDialog("PDF created", "Export Complete");
		}
	}
	catch (Exception ex)
	{
		HideExportDialog("PDF failed", "PDF Generation Failed");
		System.Diagnostics.Debug.WriteLine(ex);
	}
}
private void btnExportDXF_Click(object sender, EventArgs e)
{
	string fullFileName = GetFullSavePathAndDeleteIfExists(EXPORT_FILENAME, "dxf");
	string fullPathIniSaveName = System.IO.Path.Combine(FILE_PATH, EXPORT_FILENAME);
	fullPathIniSaveName = System.IO.Path.ChangeExtension(fullPathIniSaveName, "ini");

	ShowExportDialog("Exporting DXF", fullFileName, true);
	try
	{
		TranslatorAddIn oDXFTrans = (TranslatorAddIn)m_application.ApplicationAddIns.ItemById["{C24E3AC4-122E-11D5-8E91-0010B541CD80}"];
		if (null == oDXFTrans)
		{
			MessageBox.Show("Could not load DXF Translator addin", "Export Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
			return;
		}

		TranslationContext oContext = m_application.TransientObjects.CreateTranslationContext();
		oContext.Type = IOMechanismEnum.kFileBrowseIOMechanism;

		NameValueMap oOptions = m_application.TransientObjects.CreateNameValueMap();
		if (oDXFTrans.HasSaveCopyAsOptions[m_idw, oContext, oOptions])
		{
			DataMedium oData = m_application.TransientObjects.CreateDataMedium();

			oOptions.Value["Publish_Mode"] = DWFPublishModeEnum.kCustomDWFPublish;
			oOptions.Value["Export_Acad_IniFile"] = fullPathIniSaveName;
			oOptions.Value["All_Color_AS_Black"] = true;

			oOptions.Value["Sheets"] = GetSheetOptions();

			oData.FileName = fullFileName;
			oDXFTrans.SaveCopyAs(m_idw, oContext, oOptions, oData);
			HideExportDialog("DXF created", "Success");
		}
	}
	catch (Exception ex)
	{
		HideExportDialog("DXF failed", "DXF Generation Failed");
		System.Diagnostics.Debug.WriteLine(ex);
	}
}

As you successfully run the program, you realize you are done adding all the features you need. Now is the fun part: cleaning up code, optimizing, and automating everything. You decide this is how you will show your application off to Sir Sam “the doubter” Bossman. Your current dialog setup requires you to manually go through the steps, as you programmed them. Let’s just add a shift key check on the [Start Inventor] button click that will call a method to cycle through all the steps you created, without stopping. Here is your final modification to the code.

private bool m_automating = false;

private void btnHook_Click(object sender, EventArgs e)
{
	bool isShiftKeyDown = Control.ModifierKeys == Keys.Shift;

	m_application = InitializeInventor(true, true);
	m_application.AssemblyOptions.DeferUpdate = false;
	CloseAllDocuments();
	AddInCleanup();
	m_projectFileSet = false;
	SetButtonStates();

	if (isShiftKeyDown)
	{
		RunToTheHills();
	}
}

private void RunToTheHills()
{
	m_automating = true;

	btnLoadProjectFile_Click(null, null);
	btnLoadMainAssembly_Click(null, null);
	btnLoadPart1_Click(null, null);
	btnLoadPart2_Click(null, null);
	btnLoadPart3_Click(null, null);
	btnLoadPart4_Click(null, null);
	btnLoadIDW_Click(null, null);
	btnCreateBaseView_Click(null, null);
	btnProjectedView_Click(null, null);
	btnScaleBaseView_Click(null, null);
	btnPositionBaseView_Click(null, null);
	btnPositionProjectedView_Click(null, null);
	btnInsertBreak_Click(null, null);
	btnAddDimension_Click(null, null);
	btnInsertSymbol_Click(null, null);
	//
	btnExportPDF_Click(null, null);
	btnExportDXF_Click(null, null);
	btnSave_Click(null, null);
	btnSaveIDWasJPG_Click(null, null);

	m_automating = false;
	MessageBox.Show("Automation Cycle is complete", "Success", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
}

You run it a few times and realize that there is really nothing more to do to show the boss what you have accomplished. You glance down at the clock in the lower corner of your screen and notice it is only 9:30. You decide to customize your desktop and do a little web browsing until your boss shows up. After about 25 minutes, you get bored and lean back on your chair with your feet up and your arms behind your head. At that instant (naturally), Sam opens up the door and leans in with a smirk on his face, saying “I know it is only 10:00, do you think you can show me now, I got a meeting soon and I’m not sure I will be able to make our 10:30. You sit up and reply with “Sure can, come on over and take a look”. You notice this takes him by surprise as he was positive he was going to catch you off guard. But you know better. As he circles around your desk, you load up the program and shift-click the start button. Here is what he saw.

After the demo was over, he stood there staring at the screen like a kid gazing through the glass counter at a candy store. After a few seconds, he pats you on the back and says “Very nice job, I knew you could do this! I have to admit, I thought you were messing around this week, but I was wrong. This is very nice.” You say thank you as he retreats to the door. This is what work is all about. Making what seems impossible possible!

Start typing and press Enter to search