public static SPWorkflowAssociation EnsureWorkflowAssociation(SPWorkflowAssociationCollection collection, Guid workflowBaseId, SPWorkflowAssociationCreator createDelegate, out bool associationUpdated) { CommonHelper.ConfirmNotNull(collection, "collection"); CommonHelper.ConfirmNotNull(createDelegate, "createDelegate"); associationUpdated = false; SPWeb targetWeb = collection.ParentWeb; SPWorkflowAssociation wfAssoc = collection.GetAssociationByBaseIDSafe(workflowBaseId); if (wfAssoc == null) { SPWorkflowTemplate wfTemplate = targetWeb.WorkflowTemplates[workflowBaseId]; if (wfTemplate == null) { throw new ArgumentOutOfRangeException("workflowBaseId", "Workflow template with the specified base ID does not exist in this site"); } SPList taskList = EnsureList(targetWeb, SPListTemplateType.Tasks, SPResource.GetString("DefaultWorkflowTaskListName", new object[0])); SPList historyList = EnsureList(targetWeb, SPListTemplateType.WorkflowHistory, SPResource.GetString("DefaultWorkflowHistoryListName", new object[0])); wfAssoc = createDelegate(wfTemplate, wfTemplate.Name, taskList, historyList); collection.Add(wfAssoc); associationUpdated = true; } if (!wfAssoc.Enabled) { wfAssoc.Enabled = true; collection.Update(wfAssoc); associationUpdated = true; } return(wfAssoc); }
//Methode: SharePoint-Designer-Workflow wird gestartet. public void StartSPWorkflow(String workflowName) { SPWorkflowAssociationCollection associationCollection = listItemOrder.ParentList.WorkflowAssociations; //Mit foreach wird durch alle vorhandenen Workflows in der Websitesammlung gegangen foreach (SPWorkflowAssociation association in associationCollection) { //Wenn einer der Workflownamen dem Angegebenen (dh. <string workflow>) entspricht wird der enthaltene Code ausgeführt if (association.Name == workflowName) { //Überprüfen ob eine weitere Instanz des gleichen Workflows schon ausgeführt wird. //Das ist nötig, wenn eine Drittlandsbestellung gemacht wird. Dabei wird der Workflow solange angehalten/pausiert bis die Zollbeauftragten den Auftrag genehmigt haben. //Wenn vor der Genehmigung etwas am Auftrag geändert wird, muss der SP-Designer-WF erneut gestartet werden. Da die vorige Instanz des Workfows aber noch läuft und nur pausiert ist, //schlägt das Starten des Workflows fehl. foreach (SPWorkflow spworkflow in site.WorkflowManager.GetItemActiveWorkflows(listItemOrder)) { //Überprüft wird, ob die AssocationId übereinstimmt --> wenn ja, wird diese Instanz mit "CancelWorkflow" abgebrochen if (spworkflow.AssociationId == association.Id) { SPWorkflowManager.CancelWorkflow(spworkflow); } } association.AutoStartChange = true; association.AutoStartCreate = false; association.AssociationData = string.Empty; //Befehl zum Starten des Workflows site.WorkflowManager.StartWorkflow(listItemOrder, association, association.AssociationData); } } }
private static void StartWorkflow(SPListItem listItem, string workflowName) { try { SPWorkflowManager manager = listItem.Web.Site.WorkflowManager; SPWorkflowAssociationCollection objWorkflowAssociationCollection = listItem.ParentList.WorkflowAssociations; foreach (SPWorkflowAssociation objWorkflowAssociation in objWorkflowAssociationCollection) { if (String.Compare(objWorkflowAssociation.Name, workflowName, true) == 0) { //We found our workflow association that we want to trigger. //Replace the workflow_GUID with the GUID of the workflow feature that you //have deployed. try { manager.StartWorkflow(listItem, objWorkflowAssociation, objWorkflowAssociation.AssociationData, true); //The above line will start the workflow... } catch (Exception) { } break; } } } catch (Exception) {} }
public static void StartWorkflow(SPListItem listItem, string workflowName, SPWorkflowRunOptions runOption) { try { SPWorkflowManager manager = listItem.Web.Site.WorkflowManager; SPWorkflowAssociationCollection objWorkflowAssociationCollection = listItem.ParentList.WorkflowAssociations; Debug.WriteLine("WF.Count=" + objWorkflowAssociationCollection.Count.ToString()); foreach (SPWorkflowAssociation objWorkflowAssociation in objWorkflowAssociationCollection) { Debug.WriteLine("WF.InternalName=" + objWorkflowAssociation.InternalName); Debug.WriteLine("WF.Id=" + objWorkflowAssociation.Id.ToString()); if (String.Compare(objWorkflowAssociation.Name, workflowName, true) == 0) { Debug.WriteLine("WF.Selected"); try { SPWorkflowCollection wfc = manager.GetItemActiveWorkflows(listItem); bool isActive = false; foreach (SPWorkflow wf in wfc) { Debug.WriteLine("WF.InternalName=" + wf.ItemName); // wf.IsCompleted nie używać - blokuje kolejne uruchomienie procesu jeżęli status jest "Ukończono" if (wf.IsLocked && objWorkflowAssociation.Id.Equals(wf.AssociationId)) { isActive = true; Debug.WriteLine("WF.IsLocked=" + wf.IsLocked.ToString()); Debug.WriteLine("WF.AssociationId=" + wf.AssociationId.ToString()); break; } } if (!isActive) { SPWorkflow spw = manager.StartWorkflow(listItem, objWorkflowAssociation, objWorkflowAssociation.AssociationData, runOption); Debug.WriteLine("Workflow: " + workflowName + " Internal State: " + spw.InternalState); //The above line will start the workflow... } else { Debug.WriteLine("WF aktualnie uruchomiony - kolejna aktywacja procesu przerwana"); //ElasticEmail.EmailGenerator.SendMail("wf aktualnie uruchomiony" + listItem.ID.ToString(), string.Empty); } } catch (Exception) { } break; } } } catch (Exception) { } }
public WorkflowAssociationCollectionNode(object parent, SPWorkflowAssociationCollection workFlowCollection) { this.Tag = workFlowCollection; this.SPParent = parent; this.Setup(); this.Nodes.Add(new ExplorerNodeBase("Dummy")); }
public WorkflowAssociationCollectionNode(object parent, SPWorkflowAssociationCollection workFlowCollection) { this.Tag = workFlowCollection; this.SPParent = parent; this.Setup(); this.Nodes.Add(new ExplorerNodeBase("Dummy")); }
public SPWorkflowAssociationCollectionInstance(ObjectInstance prototype, SPWorkflowAssociationCollection workflowAssociationCollection) : this(prototype) { if (workflowAssociationCollection == null) { throw new ArgumentNullException("workflowAssociationCollection"); } m_workflowAssociationCollection = workflowAssociationCollection; }
public SPWorkflowAssociationInstance GetWorkflowAssociationByName(SPListItemInstance listItem, object id) { if (listItem == null) { throw new JavaScriptException(Engine, "Error", "ListItem must be specified as the first argument."); } var guidId = GuidInstance.ConvertFromJsObjectToGuid(id); var result = SPWorkflowAssociationCollection.GetAssociationForListItemById(listItem.ListItem, guidId); return(result == null ? null : new SPWorkflowAssociationInstance(Engine.Object.InstancePrototype, result)); }
public static SPWorkflow StartWorkflow(SPListItem listItem, string workflowName) { SPWorkflow wf = null; try { SPWorkflowManager manager = listItem.Web.Site.WorkflowManager; SPWorkflowAssociationCollection objWorkflowAssociationCollection = listItem.ParentList.WorkflowAssociations; foreach (SPWorkflowAssociation objWorkflowAssociation in objWorkflowAssociationCollection) { if (String.Compare(objWorkflowAssociation.Name, workflowName, true) == 0) { //We found our workflow association that we want to trigger. //Replace the workflow_GUID with the GUID of the workflow feature that you //have deployed. try { //result = manager.StartWorkflow(listItem, objWorkflowAssociation, objWorkflowAssociation.AssociationData, SPWorkflowRunOptions.SynchronousAllowPostpone); wf = manager.StartWorkflow(listItem, objWorkflowAssociation, objWorkflowAssociation.AssociationData, true); //ElasticEmail.EmailGenerator.SendMail("StartWorkflow: " + workflowName + " " + wf.InternalState.ToString(), ""); //manager.StartWorkflow(listItem, objWorkflowAssociation, objWorkflowAssociation.AssociationData, true); //The above line will start the workflow... } catch (Exception) { } break; } } } catch (Exception) { } return(wf); }
/// <summary> /// An item was updated. /// </summary> public override void ItemUpdated(SPItemEventProperties properties) { base.ItemUpdated(properties); //Ausführen des folgenden Codes nur, wenn ein PDF vorhanden ist if (properties.ListItem.Name.Contains(".pdf")) { //Durch folgende Zeile wird der enthaltene Code als SHAREPOINT\System ausgeführt und nicht unter dem Kontext des Benutzers, der den Auftrag unterschrieben hat SPSecurity.RunWithElevatedPrivileges(delegate() { //Laden des aktuellen Webs; das ist nötig, um alle möglichen Operationen mit Bibliotheken und Elementen auszuführen //dieses wird wieder geschlossen bzw. freigegeben, wenn die geschweifte Klammer von "using" geschlossen wird using (SPSite site = new SPSite(properties.WebUrl)) { using (SPWeb web = site.OpenWeb()) { //Festlegen von Variablen //Initialisieren der "Helper"-Klasse. Diese enthält selbst geschriebene Methoden, die hier aufgerufen werden. Helper helper = new Helper(); //Laden des aktuell geänderten bzw. unterschrieben Elements SPListItem _currentItem = web.Lists[properties.ListId].GetItemById(properties.ListItemId); //Abspeichern von Spaltenwerten des Elements in Variablen; der String in den eckigen Klammern ist der Spaltenname string auftragsnummer = _currentItem["Auftragsnummer"].ToString(); string bestellmethode = _currentItem["Bestellmethode"].ToString(); SPFieldBoolean DrittlandBoolField = _currentItem.Fields["Drittland"] as SPFieldBoolean; bool Drittland = (bool)DrittlandBoolField.GetFieldValue(_currentItem["Drittland"].ToString()); string DocID = _currentItem.Properties["_dlc_DocId"].ToString(); //Die Summe muss in ein double-Wert umgewandelt werden, damit er später richtig verwendet werden kann double summe = Convert.ToDouble(_currentItem["Summe"]); //Laden der Bibliothek "Temp" und des Unterordners, welcher als Namen die Auftragsnummer hat SPList tempbibliothek = web.Lists["Temp"]; var tempfolder = web.GetFolder(String.Format("{0}/Temp/" + auftragsnummer, web.Url)); //Angabe des Namens der Bibliothek, in der die Begründungen gespeichert werden, und des Dateinamens der Begründungen //string begruendungbibliothek = "Begruendungen"; string begruendungbibliothek = "Begründungen"; string begruendungdateiname = auftragsnummer + "_InterneBegruendung.pdf"; string auftragdesturl = tempbibliothek.RootFolder.SubFolders[auftragsnummer].Url + "/" + auftragsnummer + ".pdf"; string begruendungdesturl = tempbibliothek.RootFolder.SubFolders[auftragsnummer].Url + "/" + begruendungdateiname; //Angabe des Namens der Bibliothek der Auftragsformulare und deren Dateinamen string formularbibliothek = "Auftragsformular"; string formulardateiname = auftragsnummer + ".xml"; string xanhang = "my:Anhang"; string xweitergabe = "my:Weitergabe"; //Angeben des Pfades zum Ablegen des zusammengefassten PDFs für den Druck für die VW //Bei Pfadangaben mit Backslashes muss entweder vor dem Anführungszeichen ein @ geschrieben werden ODER doppelte Backslashes verwendet werden (z.B. "C:\\ipm-int\\Bestellungen\\") string pdfpath = @"C:\Bestellung\PrintTemp\PDF\"; //Angeben des Druckers über den gedruckt wird; hier ist einfach der Freigabename anzugeben //string printer = @"\\ipm-int\Bestellungen\"; string printer = @"\\printserver\A-3-31-SW-Buero\"; //Definieren einer vorerst leeren String-Variable string davorsigniert = ""; //Wenn die Spalte "SignaturePreviousSigned" nicht leer ist, wird der enthaltene Wert der Variable "davorsigniert" zugwiesen if (_currentItem["SignaturePreviousSigned"] != null) { davorsigniert = _currentItem["SignaturePreviousSigned"].ToString(); } //Auslesen der Empfänger-Adressen aus den SharePoint-Gruppen string rcptFaxPostalOrders = ""; string spGroupRcptFaxPostalFiles = "Empfänger der Fax - und Postbestellungen"; foreach (SPUser user in web.SiteGroups[spGroupRcptFaxPostalFiles].Users) { rcptFaxPostalOrders += user.Email.ToString() + ";"; } Console.WriteLine(rcptFaxPostalOrders); //Die Drittlands-Mail inkl. Anlagen soll seit 13.02.2019 laut Verwaltung nur noch an das Einkaufs-Postfach gehen. string rcptThirdCountryOrders = ""; string spGroupRcptCustomFiles = "Empfänger der Drittlandsbestellungen"; foreach (SPUser user in web.SiteGroups[spGroupRcptCustomFiles].Users) { rcptThirdCountryOrders += user.Email.ToString() + ";"; } string rcptBbc = ""; string spGroupRcptBbc = "E-Mails der Ereignisempfänger (BBC) "; foreach (SPUser user in web.SiteGroups[spGroupRcptBbc].Users) { rcptBbc += user.Email.ToString() + ";"; } //Erstellen der byte-Arrays für die PDF-Dateien die durch Mergen/Zusammenfügen erstellt werden; eins für den Empfang zum faxen, das andere für den Ausdruck für die Verwaltung byte[] mergeresultbyte = new byte[0]; byte[] mergeresultbytevw = new byte[0]; //Festlegen des Dateinamens unter dem das PDF für den Ausdurck für die Verwaltung im lokalen Dateisystem abgespeichert wird. string mergefilenamevw = auftragsnummer + "_vw.pdf"; //Laden des gerade signierten PDFs; zuerst wird es als SharePoint-Datei (SPFile) geladen, dann als Byte-Array. SPFile auftragszettel = _currentItem.File; byte[] auftragszettelbyte = auftragszettel.OpenBinary(); //Initialisieren eines PDFReaders (von itextsharp) mit Verweis auf das eben geöffnete Byte-Array; der PDF-Reader kann PDF-Dateien nur lesen using (PdfReader pdfreader = new PdfReader(auftragszettelbyte)) { //Laden der vorhandenen PDF-Formularfelder AcroFields fields = pdfreader.AcroFields; //Speichern der Namen aller signierten Felder in disem PDF in Liste "signatures". Die zu signierenden Felder heißen "Projektleiter" und "Verwaltung"; demnach kann dieser Wert leer, "Projektleiter" oder "ProjektleiterVerwaltung" sein List <string> signatures = pdfreader.AcroFields.GetSignatureNames(); //Die gerade gespeicherten Feldnamen werden mit Komma getrennt (wenn mehrere vorhanden sind) und in eine neue String-Variable gespeichert. Somit wird aus "ProjektleiterVerwaltung" > "Projektleiter,Verwaltung" string signiert = string.Join(",", signatures.ToArray()); //Anhand dieser IF-Abfrage wird geprüft ob der Auftag überhaupt signiert wurde. Es wird der Spaltenwert ("SignaturePreviousSigned") mit den im PDF tatsächlich signierten Feldern verglichen if (signiert != davorsigniert) { //Starten des SharePoint-Designer-Workflows "Unterschriftenlauf" mit Parameter "signedfields". Mit diesem Parameter werden die Namen der Signierten Felder direkt als String mitgegeben. SPWorkflowAssociationCollection associationCollection = _currentItem.ParentList.WorkflowAssociations; foreach (SPWorkflowAssociation association in associationCollection) { if (association.Name == "Unterschriftenlauf") { association.AutoStartChange = true; association.AutoStartCreate = false; association.AssociationData = "<Data><Signiert>" + signiert + "</Signiert></Data>"; //web.Site.WorkflowManager.StartWorkflow(_currentItem, association, association.AssociationData); site.WorkflowManager.StartWorkflow(_currentItem, association, association.AssociationData); } } //Der SharePoint-Designer-Workflow geht nun alle vorhandenen Fälle durch und versendet die nötigen Benachrichtigungen und ändert das Status-Feld des Auftrags //Im Code muss nun nur noch der Fall beachtet werden, wenn Projektleiter und Verwaltung unterschrieben haben //In diesem Fall muss ein PDF für die Verwaltung und eins (nur wenn nötig) für den Empfang erstellt werden. Letzteres wird benötigt, um dem Empfang dieses per Mail zu versenden, damit es gefaxt oder per Post versendet werden kann. //Das ist nur nötig, wenn die Bestellmethode NICHT "online" oder "Abholung" ist //Zu aller erst wird überprüft ob der beschriebene Fall eintritt: Die Variable "signiert" enthält alle Namen der Signaturfelder aus dem PDf, die unterschrieben sind. if ((signiert == "Projektleiter,Verwaltung") || (signiert == "Verwaltung,Projektleiter")) { string tempuploadurl = helper.TempOrdner(tempbibliothek, tempfolder, auftragsnummer); //Laden des Auftragsformulars byte[] xmlfile = helper.GetFileFromWeb(formularbibliothek, formulardateiname, web); Stream xmlmemstr = new MemoryStream(xmlfile); XmlDocument xmldoc = new XmlDocument(); xmldoc.Load(xmlmemstr); XPathNavigator root = xmldoc.CreateNavigator(); XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable()); //Angeben des NameSpaces: Die Werte werden direkt aus einem beispiel Formular entnommen (stehen am Anfang der XML-Datei) nsmgr.AddNamespace("my", "http://schemas.microsoft.com/office/infopath/2003/myXSD/2016-04-22T15:49:19"); helper.AnlagenHochladen(root.Select("/my:meineFelder/my:Anlagen/my:Anlage", nsmgr), xanhang, xweitergabe, nsmgr, DocID, tempfolder, tempuploadurl, web); //Hochladen der Begründung und des aktuellen Auftragzettels in den Temp-Ordner //Begründung if (root.SelectSingleNode("/my:meineFelder/my:Begruendung", nsmgr).ToString() != "") { byte[] fattenedBegruendung = helper.flattenPdfForm(helper.GetFileFromWeb(begruendungbibliothek, begruendungdateiname, web)); SPFile copybegruendung = tempfolder.Files.Add(begruendungdesturl, fattenedBegruendung, true); SPListItem copybegruendungitem = copybegruendung.Item; copybegruendungitem["Auftragsnummer"] = auftragsnummer; //Übernehmen der Änderung. Durch "SystemUpdate" wird diese Änderung nicht in SharePoint selbst dokumentiert (in Spalten "geändert von" und "geändert"). copybegruendungitem.SystemUpdate(); } //Auftragszettel byte[] flattendAuftrag = helper.flattenPdfForm(auftragszettelbyte); SPFile copyauftrag = tempfolder.Files.Add(auftragdesturl, flattendAuftrag, true); //Setzen des Spaltenwerts "Weitergabe" auf true, da der Lieferant den Auftragszettel immer erhalten muss. Wäre dieser WErt auf "false" würde Auftragszettel beim PDf für Fax oder Post fehlen. Der Wert ist in der SharePoint-Bibliothek "Temp" standardmäßig auf "false" gesetzt. SPListItem copyauftragitem = copyauftrag.Item; copyauftragitem["Weitergabe"] = true; copyauftragitem.SystemUpdate(); //diese IF-Abfrage ist nur reine Sicherheitsmaßnahme: Es wird geprüft ob im Temp-Ordner auch Dateien vorhanden sind. Da der Auftrag direkt davor in diesen Ordner kopiert wird sollte diese Bedingung immer zutreffen. if (tempfolder.ItemCount > 0) { //Zusammenführen aller PDF-Dokumente für die Verwaltung //SPListItemCollection ist eine Sammlung von SharePoint-Elementen. Welche Elemente ausgewählt werden, ist in der Helper-Methode (ganz unten) nach zu lesen. Mit dem Übergabewert "false" wird bewirkt, dass nicht beachtet wird, welche Anlagen zur Weitergabe an den Lieferanten gewählt sind - es wird alles einfach gedruckt. SPListItemCollection pdfcollection = helper.CollectPDF(tempfolder, tempbibliothek, false); //Die zuvor erstellte Sammlung von Elementen ("pdfcollection") wird nun in einer weiteren Helper-Methode verwendet, um die PDf-Dateien zu kombinieren. Mit dem Übergabewert "false" wird bewirkt, dass die AEB's NICHT mit ausgedruckt werden. mergeresultbytevw = helper.Merge(pdfcollection, false, auftragsnummer); //Zusammenführen der PDf-Dokumente für den Lieferanten //Gemerged wird nur, wenn über Fax oder Post bestellt wird, damit die Zentrale eine Datei hat, die sie versenden/ausdrucken können. Wenn "online" oder per "Abholung" bestellt wird, oder wenn es sich um ein Drittland handelt, findet dieser Vorgang nicht statt. if ((bestellmethode.Contains("online") == false) && (bestellmethode.Contains("Abholung") == false) && Drittland == false) { //Sammeln der Elemente; diesmal mit dem Übergabewert "true", damit nur Anlagen berücksichtigt werden, die auch zur Weitergabe für den Lieferanten ausgewählt sind pdfcollection = helper.CollectPDF(tempfolder, tempbibliothek, true); //Zusammenführen der gerade gesammelten Elemente; diesmal mit dem Übergabewert "true", damit die AEBs erhalten bleiben mergeresultbyte = helper.Merge(pdfcollection, true, auftragsnummer); //Kopieren des PDF in einen lokalen Ordner auf dem SharePoint-Server File.WriteAllBytes(pdfpath + auftragsnummer + "_Kopie.pdf", mergeresultbyte); string faxnummer = "<br>"; if ((bestellmethode == "Fax") && (_currentItem["Fax"] != null)) { faxnummer = "Fax: " + _currentItem["Fax"].ToString() + "<br><br>"; } string zentraletext = "<div style='font-family: Frutiger LT COM 45 Light; font-size: 11pt;'>Guten Tag,<br><br>" + "der Auftrag #" + auftragsnummer + " wurde vom Projektleiter und der Verwaltung signiert. Als Bestellmethode wurde " + bestellmethode + " gewählt. " + "Der Auftrag ist im Anhang enthalten. Hierbei handelt es sich nur um eine Kopie für den Lieferanten.<br><br>" + "Name Besteller: " + helper.Anzeigename(_currentItem, "Profil:NameBesteller") + "<br>" + "Projektleiter: " + helper.Anzeigename(_currentItem, "Profil:Projektleiter") + "<br>" + "Firma: " + _currentItem["Firma"].ToString() + "<br>" + faxnummer + "Dies ist eine automatische Benachrichtigung. Bitte antworten Sie nicht auf diese E-Mail."; helper.Mail("Bestellung", rcptFaxPostalOrders, rcptBbc, "Auftrag #" + auftragsnummer + " - Signaturvorgang abgeschlossen", zentraletext, mergeresultbyte, auftragsnummer, site); } } else { mergeresultbytevw = auftragszettelbyte; //Auch Dieser Else-Block ist nur reine Sicherheitsmaßnahme. } //Kopieren des PDFs für VW in einen lokalen Ordner (siehe Variable "printpath") auf dem SharePoint-Server. File.WriteAllBytes(pdfpath + mergefilenamevw, mergeresultbytevw); //Hochladen des PDFs für VW in Ordner "Print" in Bibliothek "Temp" //desturl = tempbibliothek.RootFolder.SubFolders["Merged"].Url + "/" + mergefilenamevw; //SPFile uploadmerged = tempfolder.Files.Add(desturl, File.ReadAllBytes(pdfpath + mergefilenamevw), true); //Schicken der PDF-Datei für VW an den Drucker (siehe Variable "printer") if (Drittland == false) { File.Copy(pdfpath + mergefilenamevw, printer + mergefilenamevw); } else { string drittlandtext = "<div style='font-family: Frutiger LT COM 45 Light; font-size: 11pt;'>Guten Tag,<br><br>" + "der Signaturvorang für den Auftrag (#" + auftragsnummer + ") wurde abgeschlossen. Da es sich um eine Bestellung aus dem <b>Drittland</b> handelt, wird der Auftrag <b>ohne automatischen Ausdruck</b> an den Einkauf weitergeleitet. " + "Der Auftrag ist im Anhang enthalten.<br><br>" + "Name Besteller: " + helper.Anzeigename(_currentItem, "Profil:NameBesteller") + "<br>" + "Projektleiter: " + helper.Anzeigename(_currentItem, "Profil:Projektleiter") + "<br>" + "Firma: " + _currentItem["Firma"].ToString() + "<br>" + "Bestellmethode: " + bestellmethode + "<br><br>" + "Dies ist eine automatische Benachrichtigung. Bitte antworten Sie nicht auf diese E-Mail."; helper.Mail("Bestellung", rcptThirdCountryOrders, rcptBbc, "Drittland: Auftrag #" + auftragsnummer + " - Signaturvorgang abgeschlossen", drittlandtext, mergeresultbytevw, auftragsnummer, site); } //Löschen des PDFs für VW aus lokalem Ordner - NICHT MEHR NÖTIG, da der Temp-Ordner wöchentlich aufgeräumt wird. Deßhalb können beide Dateien aus Troubleshooting-Gründen aufgehoben werden. //File.Delete(pdfpath + mergefilenamevw); //Löschen des temporären Ordners in Bibliothek "Temp" tempfolder.Delete(); } } } } } }); } }
/// <summary> /// An item was updated. /// </summary> public override void ItemUpdated(SPItemEventProperties properties) { base.ItemUpdated(properties); if (properties.ListItem.Name.Contains(".pdf")) { //Durch folgende Zeile wird der enthaltene Code als SHAREPOINT\System ausgeführt und nicht unter dem Kontext des Benutzers, der den Auftrag unterschrieben hat SPSecurity.RunWithElevatedPrivileges(delegate() { //Laden des aktuellen Webs; das ist nötig, um alle möglichen Operationen mit Bibliotheken und Elementen auszuführen //dieses wird wieder geschlossen bzw. freigegeben, wenn die geschweifte Klammer von "using" geschlossen wird using (SPSite site = new SPSite(properties.WebUrl)) { using (SPWeb web = site.OpenWeb()) { //Festlegen von Variablen //Initialisieren der "Helper"-Klasse. Diese enthält selbst geschriebene Methoden, die hier aufgerufen werden. Helper helper = new Helper(); //Laden des aktuell geänderten bzw. unterschrieben Elements SPListItem _currentItem = web.Lists[properties.ListId].GetItemById(properties.ListItemId); //Abspeichern von Spaltenwerten des Elements in Variablen; der String in den eckigen Klammern ist der Spaltenname string requirementId = _currentItem["Title"].ToString(); string docId = _currentItem.Properties["_dlc_DocId"].ToString(); //Laden der Bibliothek "Temp" und des Unterordners, welcher als Namen die Auftragsnummer hat //Angabe des Namens der Bibliothek der Auftragsformulare und deren Dateinamen //string formLibrary = "BedarfsmeldungFormulare"; string formLibrary = "Bedarfsmeldung-Formulare"; string formFileName = requirementId + ".xml"; string xAttachment = "my:file"; string xReason = "/my:myFields/my:reason"; //Definieren einer vorerst leeren String-Variable string prevSigned = ""; //Wenn die Spalte "SignaturePreviousSigned" nicht leer ist, wird der enthaltene Wert der Variable "davorsigniert" zugwiesen if (_currentItem["SignaturePreviousSigned"] != null) { prevSigned = _currentItem["SignaturePreviousSigned"].ToString(); } //Auslesen der Empfängeradressen string rcptRequirementFiles = ""; string spGroupRcptRequirementFiles = "Empfänger der Bedarfsmeldungen"; foreach (SPUser user in web.SiteGroups[spGroupRcptRequirementFiles].Users) { rcptRequirementFiles += user.Email.ToString() + ";"; } string rcptBbc = ""; string spGroupRcptBbc = "E-Mails der Ereignisempfänger (BBC) "; foreach (SPUser user in web.SiteGroups[spGroupRcptBbc].Users) { rcptBbc += user.Email.ToString() + ";"; } //Laden des gerade signierten PDFs; zuerst wird es als SharePoint-Datei (SPFile) geladen, dann als Byte-Array. SPFile requirementPdf = _currentItem.File; byte[] requirementPdfByte = requirementPdf.OpenBinary(); //Initialisieren eines PDFReaders (von itextsharp) mit Verweis auf das eben geöffnete Byte-Array; der PDF-Reader kann PDF-Dateien nur lesen using (PdfReader pdfreader = new PdfReader(requirementPdfByte)) { //Laden der vorhandenen PDF-Formularfelder AcroFields fields = pdfreader.AcroFields; //Speichern der Namen aller signierten Felder in disem PDF in Liste "signatures". Die zu signierenden Felder heißen "Projektleiter" und "Verwaltung"; demnach kann dieser Wert leer, "Projektleiter" oder "ProjektleiterVerwaltung" sein List <string> signatures = pdfreader.AcroFields.GetSignatureNames(); //Die gerade gespeicherten Feldnamen werden mit Komma getrennt (wenn mehrere vorhanden sind) und in eine neue String-Variable gespeichert. Somit wird aus "ProjektleiterVerwaltung" > "Projektleiter,Verwaltung" string signed = string.Join(",", signatures.ToArray()); //Anhand dieser IF-Abfrage wird geprüft ob der Auftag überhaupt signiert wurde. Es wird der Spaltenwert ("SignaturePreviousSigned") mit den im PDF tatsächlich signierten Feldern verglichen if (signed != prevSigned) { //Starten des SharePoint-Designer-Workflows "Unterschriftenlauf" mit Parameter "signedfields". Mit diesem Parameter werden die Namen der Signierten Felder direkt als String mitgegeben. SPWorkflowAssociationCollection associationCollection = _currentItem.ParentList.WorkflowAssociations; foreach (SPWorkflowAssociation association in associationCollection) { if (association.Name == "Bedarfsmeldung - Genehmigungsvorgang") { //Überprüfen ob eine weitere Instanz des gleichen Workflows schon ausgeführt wird. //Das ist nötig, wenn eine Drittlandsbestellung gemacht wird. Dabei wird der Workflow solange angehalten/pausiert bis die Zollbeauftragten den Auftrag genehmigt haben. //Wenn vor der Genehmigung etwas am Auftrag geändert wird, muss der SP-Designer-WF erneut gestartet werden. Da die vorige Instanz des Workfows aber noch läuft und nur pausiert ist, //schlägt das Starten des Workflows fehl. foreach (SPWorkflow spworkflow in site.WorkflowManager.GetItemActiveWorkflows(_currentItem)) { //Überprüft wird, ob die AssocationId übereinstimmt --> wenn ja, wird diese Instanz mit "CancelWorkflow" abgebrochen if (spworkflow.AssociationId == association.Id) { SPWorkflowManager.CancelWorkflow(spworkflow); } } association.AutoStartChange = true; association.AutoStartCreate = false; association.AssociationData = "<Data><Signiert>" + signed + "</Signiert></Data>"; //web.Site.WorkflowManager.StartWorkflow(_currentItem, association, association.AssociationData); site.WorkflowManager.StartWorkflow(_currentItem, association, association.AssociationData); } } //Der SharePoint-Designer-Workflow geht nun alle vorhandenen Fälle durch und versendet die nötigen Benachrichtigungen und ändert das Status-Feld des Auftrags //Im Code muss nun nur noch der Fall beachtet werden, wenn Projektleiter und Verwaltung unterschrieben haben //In diesem Fall muss ein PDF für die Verwaltung und eins (nur wenn nötig) für den Empfang erstellt werden. Letzteres wird benötigt, um dem Empfang dieses per Mail zu versenden, damit es gefaxt oder per Post versendet werden kann. //Das ist nur nötig, wenn die Bestellmethode NICHT "online" oder "Abholung" ist //Zu aller erst wird überprüft ob der beschriebene Fall eintritt: Die Variable "signiert" enthält alle Namen der Signaturfelder aus dem PDf, die unterschrieben sind. if (signed == "Projektleiter") { SPList tempLibrary = web.Lists["Temp"]; var tempFolder = web.GetFolder(String.Format("{0}/Temp/" + requirementId, web.Url)); //Angabe des Namens der Bibliothek, in der die Begründungen gespeichert werden, und des Dateinamens der Begründungen string urlRequirementInTempFolder = tempLibrary.RootFolder.SubFolders[requirementId].Url + "/" + requirementId + ".pdf"; string tempuploadurl = helper.TempOrdner(tempLibrary, tempFolder, requirementId); //Laden des Auftragsformulars byte[] xmlfile = helper.GetFileFromWeb(formLibrary, formFileName, web); Stream xmlmemstr = new MemoryStream(xmlfile); XmlDocument xmldoc = new XmlDocument(); xmldoc.Load(xmlmemstr); XPathNavigator root = xmldoc.CreateNavigator(); XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable()); //Angeben des NameSpaces: Die Werte werden direkt aus einem beispiel Formular entnommen (stehen am Anfang der XML-Datei) nsmgr.AddNamespace("my", "http://schemas.microsoft.com/office/infopath/2003/myXSD/2019-02-06T08:35:46"); helper.UploadAttachments(root.Select("/my:myFields/my:attachments/my:attachment", nsmgr), xAttachment, nsmgr, docId, tempFolder, tempuploadurl, web); string reasonFolder = "Begruendungen"; string reasonLibrary = "Begründungen"; string reasonFileName = requirementId + "_Begruendung.pdf"; string urlReasonInTempFolder = tempLibrary.RootFolder.SubFolders[requirementId].Url + "/" + reasonFileName; if (root.SelectSingleNode(xReason, nsmgr).ToString() != "") { byte[] reasonPdf = helper.GetFileFromWeb(reasonLibrary, reasonFileName, web); SPFile spFileReason = tempFolder.Files.Add(urlReasonInTempFolder, reasonPdf, true); } //Bedarfsmeldungs-Pdf byte[] flattenedRequirementPdf = helper.flattenPdfForm(requirementPdfByte); SPFile spFileRequirementPdf = tempFolder.Files.Add(urlRequirementInTempFolder, flattenedRequirementPdf, true); //Setzen des Spaltenwerts "Weitergabe" auf true, da der Lieferant den Auftragszettel immer erhalten muss. Wäre dieser WErt auf "false" würde Auftragszettel beim PDf für Fax oder Post fehlen. Der Wert ist in der SharePoint-Bibliothek "Temp" standardmäßig auf "false" gesetzt. //SPListItem spItemRequirementPdf = spFileRequirementPdf.Item; //spItemRequirementPdf.SystemUpdate(); //diese IF-Abfrage ist nur reine Sicherheitsmaßnahme: Es wird geprüft ob im Temp-Ordner auch Dateien vorhanden sind. Da der Auftrag direkt davor in diesen Ordner kopiert wird sollte diese Bedingung immer zutreffen. if (tempFolder.ItemCount > 0) { SPListItemCollection itemCollection = helper.CollectFiles(tempFolder, tempLibrary, false); string mailText = "<div style='font-family: Frutiger LT COM 45 Light; font-size: 11pt;'>Guten Tag,<br><br>" + "die Bedarfsmeldung #" + requirementId + " wurde vom Projektleiter signiert. " + "Die Bedarfsmeldung und die zugehörigen Anlagen sind im Anhang enthalten.<br><br>" + "Name Besteller: " + helper.GetUserDisplayName(_currentItem, "Name Besteller") + "<br>" + "Projektleiter: " + helper.GetUserDisplayName(_currentItem, "Projektleiter") + "<br><br>" + "Dies ist eine automatische Benachrichtigung. Bitte antworten Sie nicht auf diese E-Mail."; helper.Mail("Bestellung", rcptRequirementFiles, rcptBbc, "Neue Bedarfsmeldung (#" + requirementId + ")", mailText, itemCollection, requirementId, site); } tempFolder.Delete(); } } } } } }); } }
/// <summary> /// Ensures the approval workflow on list. /// </summary> /// <param name="web">The web.</param> /// <param name="list">The list.</param> /// <param name="events">The events.</param> /// <param name="useSamlWorkflow">Whether to use the SAML Approval workflow</param> /// <returns> /// The workflow subscription id /// </returns> /// <exception cref="System.ArgumentNullException"></exception> public static Guid EnsureApprovalWorkflowOnList(SPWeb web, SPList list, List <WorkflowStartEventType> events, bool useSamlWorkflow) { Guid subscriptionId = Guid.Empty; if (list == null) { throw new ArgumentNullException("list"); } // Remove existing 2010 workflow associations SPWorkflowAssociationCollection existingWorkflows = list.WorkflowAssociations; if (existingWorkflows != null) { for (int i = 0; i < existingWorkflows.Count; i++) { list.WorkflowAssociations.Remove(existingWorkflows[i]); } } //SPFeature customWorkflowActivitiesFeature = web.Features[customWorkflowActivitiesFeatureId]; //if (customWorkflowActivitiesFeature == null) //{ // customWorkflowActivitiesFeature = web.Features.Add(customWorkflowActivitiesFeatureId); //} SPFeature customWorkflowFeature = web.Features[customWorkflowFeatureId]; if (customWorkflowFeature == null) { customWorkflowFeature = web.Features.Add(customWorkflowFeatureId); } if (customWorkflowFeature != null) { if (!list.EnableModeration || !list.ForceCheckout) { list.EnableModeration = true; list.ForceCheckout = true; list.EnableVersioning = true; list.Update(); } Dictionary <string, string> workflowPropertyData = GetApprovalWorkflowSettings(web, list.Title); SPList taskList = EnsureWorkflowTaskList(web, "/lists/workflowtasks", string.Empty); SPList historyList = EnsureWorkflowHistoryList(web, "/workflowhistory", string.Empty); if (taskList != null && historyList != null) { bool workflowTaskContentTypeAssociated = false; foreach (SPContentType contentType in taskList.ContentTypes) { if (contentType.Parent.Id.ToString().Equals(ContentTypeWorkflowTaskSharePoint2013, StringComparison.OrdinalIgnoreCase)) { workflowTaskContentTypeAssociated = true; break; } } if (!workflowTaskContentTypeAssociated) { SPContentType wftaskContentType = default(SPContentType); SPContentTypeCollection contentTypes = web.ContentTypes.Count == 0 ? web.Site.RootWeb.ContentTypes : web.ContentTypes; wftaskContentType = contentTypes.Cast <SPContentType>().FirstOrDefault <SPContentType>(c => c.Id.ToString().Equals(ContentTypeWorkflowTaskSharePoint2013, StringComparison.OrdinalIgnoreCase)); if (wftaskContentType != null) { taskList.ContentTypes.Add(wftaskContentType); } } string displayName = ResourcesHelper.GetLocalizedString("workflow_approval_instancename"); Guid workflowDefId = useSamlWorkflow ? approvalSamlWorkflowDefinitionId : approvalWorkflowDefinitionId; subscriptionId = EnsureWorkflowOnList(web, list, workflowDefId, displayName, events, taskList, historyList, workflowPropertyData, false); EnableWorkflowsRunAsAnApp(web); SubscribeToEventReceivers(list, false); } } return(subscriptionId); }
/// <summary> /// 已添加项. /// </summary> public override void ItemAdded(SPItemEventProperties properties) { this.EventFiringEnabled = false; base.ItemAdded(properties); if (properties.List.Title.ToLower().Equals("expense report")) { SPList list = properties.List; SPListItem item = properties.ListItem; string country = item["Country"].ToString(); string user_name = properties.Web.CurrentUser.Name; SPFolder folder = properties.Web.GetFolder(item.ParentList.RootFolder.Url + "/" + country); SPListItem country_folder; if (!folder.Exists) { country_folder = list.Items.Add(list.RootFolder.ServerRelativeUrl, SPFileSystemObjectType.Folder, country); country_folder.Update(); } else { country_folder = folder.Item; } SPFolder sub_folder = null; foreach (SPFolder sf in folder.SubFolders) { if (sf.Name == user_name) { sub_folder = sf; break; } } SPListItem user_folder; if (sub_folder == null) { user_folder = list.Items.Add(folder.ServerRelativeUrl, SPFileSystemObjectType.Folder, user_name); user_folder.Update(); } else { user_folder = sub_folder.Item; } try { string newFolder = string.Format("{0}/{1}/{2}", item.ParentList.RootFolder.Url, country, user_name); SPListItem item_new = list.AddItem(newFolder, SPFileSystemObjectType.File); item_new["Title"] = item["Title"]; item_new["Amount"] = item["Amount"]; item_new["Country"] = item["Country"]; item_new["Approvers"] = item["Approvers"]; item_new["Created"] = item["Created"]; item_new["Created By"] = item["Created By"]; foreach (string file_name in item.Attachments) { SPFile file = item.ParentList.ParentWeb.GetFile( item.Attachments.UrlPrefix + file_name); byte[] data = file.OpenBinary(); item_new.Attachments.Add(file_name, data); } item_new.Update(); //item.CopyTo(properties.WebUrl+"/"+newFolder); item.Delete(); // Start the workflow SPWorkflowAssociationCollection workflows = list.WorkflowAssociations; SPWorkflowAssociation workflow = workflows.GetAssociationByName("Expense Report Approval Workflow", System.Globalization.CultureInfo.CurrentCulture); properties.Web.Site.WorkflowManager.StartWorkflow(item_new, workflow, workflow.AssociationData, true); } catch (Exception ex) { item["Error"] = ex.ToString(); item.Update(); } } }