How to start SharePoint 2010 workflow from Infopath 2010 code behind? - sharepoint-2010

I have an Infopath 2010 template with 2 buttons: submit and cancel. When the submit button is clicked I the form is saved to a document library in SharePoint 2010 and the corresponding workflow is clicked off. The user can then open the form and cancel the request by clicking on cancel. I would like to start a different workflow when cancel is clicked. Any ideas as to how that could be done?
Thanks

I have not found a method to kick off a workflow specifically from an Infopath form. I did however find a workaround; here's how I set it up:
Added a column to my list/library that will be set to true when the cancel button is selected.
In my infopath form, add my "cancel" button.
Open the control properties for the button, and select the "Rules" action. Close out of the properties dialog.
I added a fomatting rule for the cancel button so it will only display if the first workflow has started. I also disabled all other editing controls as I only wanted the cancel option to be available.
On the Control Tools contextual tab, in the Button group, click Manage Rules.
Add a new Action rule, it should run two actions: first set the value of the column we created in the first step to true; second submit data using the main data connection.
The workflow you want to run when it is cancelled should be set to run on change. As a first step, evaluate the column created above, and if true, continue the worflow. Make sure you set the value back to false so the workflow doesn't run unintentionally.
Hope that helps.

That is not a bad workaround Nostromo but we actually ended up using the out of the box SharePoint web services to start the workflow from InfoPath code behind. Here is the method we developed to do that.
public static void StartWorkflow(string siteUrl, string docUrl,string workflowName, List<string> approvers,string description)
{
var workflow = new Workflow();
workflow.Url = siteUrl+ "/_vti_bin/workflow.asmx";
workflow.Credentials = System.Net.CredentialCache.DefaultCredentials;
XmlNode assocNode = workflow.GetTemplatesForItem(docUrl);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(assocNode.OwnerDocument.NameTable);
nsmgr.AddNamespace("wf", "http://schemas.microsoft.com/sharepoint/soap/workflow/");
XmlDocument doc = new XmlDocument();
Guid templateID = new Guid();
bool workflowFound = false;
XPathNodeIterator rows = assocNode.CreateNavigator().Select("//wf:WorkflowTemplate", nsmgr);
while (rows.MoveNext())
{
if (rows.Current.GetAttribute("Name", "").ToLower() == workflowName.ToLower())
{
doc.LoadXml(rows.Current.SelectSingleNode("wf:AssociationData/wf:string", nsmgr).Value);
XPathNavigator idNode = rows.Current.SelectSingleNode("wf:WorkflowTemplateIdSet", nsmgr);
templateID = new Guid(idNode.GetAttribute("TemplateId", ""));
workflowFound = true;
break;
}
}
if(!workflowFound)
throw new Exception("System couldn't location the workflow with name: " +workflowName);
XmlElement xmlRoot = doc.DocumentElement;
nsmgr = new XmlNamespaceManager(assocNode.OwnerDocument.NameTable);
nsmgr.AddNamespace("my", "http://schemas.microsoft.com/office/infopath/2003/myXSD");
xmlRoot.SelectSingleNode("/my:myFields/my:Description", nsmgr).InnerText = description;
XmlNode reviewersNode = xmlRoot.SelectSingleNode("/my:myFields/my:Reviewers", nsmgr);
reviewersNode.InnerXml = "";
foreach (var user in approvers)
{
XmlNode personNode = reviewersNode.AppendChild(doc.CreateElement("my:Person"));
XmlNode accountIdNode = personNode.AppendChild(doc.CreateElement("my:AccountId"));
accountIdNode.InnerText = user;
XmlNode accountTypeNode = accountIdNode.AppendChild(doc.CreateElement("my:AccountType"));
accountTypeNode.InnerText = "User";
}
XmlNode workflowNode = workflow.StartWorkflow(docUrl, templateID, doc.DocumentElement);
}

Related

Accessing custom task pane in active window - Visual Basic, VSTO

I'm creating a COM add-in in VSTO for Ppt 2013 and am having a problem referencing the custom task pane in the active window.
My code is supposed to make the custom task pane visible for the active window only, however it currently runs for all document windows.
My code is:
For Each CTP As Microsoft.Office.Tools.CustomTaskPane In Globals.ThisAddIn.CustomTaskPanes
If CTP.Window Is Globals.ThisAddIn.Application.ActiveWindow Then
CTP.Visible = True
End If
Next
The taskpane is added to each new presentation created/ opened using the below code
AddIn_control1 = New AddIn_control
AddIn_taskpane = Me.CustomTaskPanes.add(AddIn_control1, "Add-in taskpane", Me.Application.ActiveWindow)
I conducted a little experiment and turns out CustomTaskPane.Window is always ActiveWindow. So to workaround it you can keep tracking of tackpanes in some dictionary:
Dictionary<CustomTaskPane, PowerPoint.Presentation> ctpDict = new Dictionary<CustomTaskPane, PowerPoint.Presentation>();
void Application_AfterNewPresentation(PowerPoint.Presentation Pres) {
AddIn_control AddIn_control1 = new AddIn_control();
CustomTaskPane AddIn_taskpane = this.CustomTaskPanes.Add(AddIn_control1, "Add-In Taskpane", this.Application.ActiveWindow);
ctpDict.Add(AddIn_taskpane, Pres);
}
and later you can use it:
if (cptDict[CTP] == Globals.ThisAddIn.Application.ActivePresentation) {
CTP.Visible = true;
}

Event Handler Tabbed Web Browser With GeckoFX

I tried to make a tabbed web browser with geckofx. This is my code to make a new tab:
Dim t As New TabPage
Dim bro As New GeckoWebBrowser
bro.Dock = DockStyle.Fill
t.Text = "New Tab"
t.Controls.Add(bro)
TabMain.TabPages.Add(t)
TabMain.SelectedTab = t
bro.Navigate("http://www.google.com")
Now, how to handle DocumentCompleted and DocumentTitleChanged in GeckoWebBrowser? I want to show message if DocumentCompleted event triggered and change window title if DocumentTitleChanged event triggered.
Not sure about the vb.net syntax, but the principle is simple (and it should be fairly simple to transfer from c# to vb)
So, for example:
1) attach an event handler to your browser
browser.DocumentCompleted += browser_DocumentCompleted;
2) generate the method that will do what you need:
void browser_DocumentCompleted(object sender, Gecko.Events.GeckoDocumentCompletedEventArgs e)
{
GWB browser = (GWB)sender;
if (browser.Document == null) return;
//do anything you wanna do when document is completed
AnyMethodBasedOnBrowser(browser);
//e.g. access GUI elements by property binding
TabTitle = "Complete";
//or even alternatively access the control directly
var TabControl = browser.Parent;
//etc etc
}
That should do the trick for you!

c# on button click open pdf in new tab insted of downloading

I have a .aspx page and it has a button on click of which a radwindow opens .The radwindow has a new page with content including a button onclick of which a pdf is created and downloaded.I want the pdf to open in a new tab or window , so i made changes to my code -changed attachment to inline
Hashtable deviceInfo = new Hashtable();
deviceInfo.Add("FontEmbedding", "Subset");
deviceInfo.Add("DocumentTitle", String.Format("TrackitManager - {0}", reportToExport.DocumentName));
deviceInfo.Add("DocumentAuthor", "Trackit Systems Pty Ltd");
ReportProcessor reportProcessor = new ReportProcessor();
RenderingResult result = reportProcessor.RenderReport("PDF", reportToExport, deviceInfo);
if (String.IsNullOrEmpty(filename))
filename = result.DocumentName;
context.Response.Clear();
context.Response.ContentType = result.MimeType;
context.Response.Cache.SetCacheability(HttpCacheability.Private);
context.Response.Expires = -1;
context.Response.Buffer = true;
//context.Response.TransmitFile("~/Handlers/EnrollmentPDF.ashx");
context.Response.AppendHeader("Content-Disposition", string.Format("attachment; filename=\"{0}.pdf\"", filename));
context.Response.BinaryWrite(result.DocumentBytes);
context.Response.End();
But this is opening the pdf inside the radwindow itself.I want it to open in a new window but outside the radwindow.
you have to give the correct header and mimeType to tell the browser to download the file
for that you just have to add this line to replace :
context.Response.ContentType = result.MimeType;
by this line :
Response.ContentType = "application/octectstream";

vsto - determine a word document if created from blank document or open from an existing document

any expert here got any idea how I can determine a word document if created from blank document or open from an existing document.
I am using Globals.ThisAddIn.Application.ActiveDocument.Saved but it seems not enough.
This should do
if (string.IsNullOrEmpty(WordInstance.ActiveDocument.Path))
{
throw new ApplicationException("Document must be saved first");
}
for vsto developers, please go here
if (Globals.ThisAddIn.Application.ActiveDocument.Path == String.Empty)
{
Word.Dialog dlg;
Object timeout = 3000;
dlg = Globals.ThisAddIn.Application.Dialogs[
Word.WdWordDialog.wdDialogFileSaveAs];
int result = dlg.Display(ref timeout);
}
else
{
Globals.ThisAddIn.Application.ActiveDocument.Save();
}
The result will store which button is pressed (0- cancel, 1- ok, 2- close)

VSTO - Outlook 2007 - Display form before send message?

I'm new to Outlook add-in programming and not sure if this is possible:
I want to display a pop-up form (or selection) and ask for user input at the time they click Send. Basically, whenever they send out an email (New or Reply), they will be asked to select a value in a dropdown box (list items from a SQL database, preferrably).
Base on their selection, a text message will be appended to the mail's subject.
I did my research and it looks like I should use Form Regions but I'm not sure how can I display a popup/extra form when user click Send.
Also, it looks like Form Regions can be used to extend/replace current VIEW mail form but can I use it for CREATE NEW form?
Thanks for everybody's time.
You can probably add the Item Send event handler in the ThisAddIn Internal Startup method and then in the Item Send Event, call the custom form (a windows form).
In the below sample I call a custom windows form as modal dialog before the email item is send and after the send button is clicked.
private void InternalStartup()
{
this.Application.ItemSend += new ApplicationEvents_11_ItemSendEventHandler(Application_ItemSend);
}
void Application_ItemSend(object Item, ref bool Cancel)
{
if (Item is Microsoft.Office.Interop.Outlook.MailItem)
{
Microsoft.Office.Interop.Outlook.MailItem currentItem = Item as Microsoft.Office.Interop.Outlook.MailItem;
Cancel = true;
Forms frmProject = new ProjectForm();;
DialogResult dlgResult = frmProject.ShowDialog();
if (dlgResult == DialogResult.OK)
System.Windows.Forms.SendKeys.Send("%S"); //If dialog result is OK, save and send the email item
else
Cancel = false;
currentItem.Save();
currentItem = null;
}
}