Microsoft Dynamics CRM 4.0 | Small Dialog Solution (Checklistitems)

Wir Entwickler freuen uns schon auf die neuen Möglichkeiten der Dialoge ab CRM 2011. Tatsächlich begegnen wir solchen Prozessen beinahe tagtäglich. Als Beispiel habe ich mir die Projektaufgaben als “Checklistenpunkte” herausgesucht. Diese Punkte sollen simpel mit den Stati “Ja”, “Nein”, “Abgewiesen” beantwortet werden können.

checklist_1

Da ich die Projektaufgaben in meinem Beispiel über einen Vorgang manage, habe ich die Checklistenpunkte als Register den Vorgängen hinzugefügt, die sich mit der Verwaltung von Projektaufgaben befassen. Selbstverständlich bleibt es Euch überlassen, wo Ihr derartige Checklistenpunkte integriert.

Das Register enthält im Übrigen ein IFrame, welches mir die zugehörigen Checklistenpunkte anzeigt. Dies hat für mich den Vorteil, dass ich hier mit der Grid-Menü-Leiste arbeiten kann und dort mit Hilfe von ISV-Buttons die Bearbeitung der Punkte ermögliche.

checklist_2

Des weiteren ist die Ansicht “Zugeordnete Ansicht…” dahingehend angepasst, dass mir nicht nur Check-listenpunkte im Status “aktiv” angezeigt werden, sondern auch solche die sich bereits im Status “inaktiv” befinden.

Warum ich diese Anpassung vorgenommen habe? Weil ich mit den Status-Updates arbeite, um zwischen bereits erledigten bzw. zurückgewiesenen Checklistenpunkten und aktiven Punkten zu unterscheiden.

Ich wollte die Bearbeitung für den Nutzer so einfach wie möglich gestalten. Die schnellste Möglichkeit bot sich mir mit der Nutzung von ISV-Buttons

checklist_5

Um die Funktionen der Buttons zu gewährleisten benötigt Ihr folgenden Code – Achtung: Der Code enthält auch die Buttons in der eigentlichen Entitätsansicht – also einem geöffneten Checklistenpunkt (Eingefügt wird er im OnLoad()-Ereignis):

// Ersetzt MicrosoftCRM einfach durch Euren Organisationsnamen
Approve = function() {
var ackn = '1';
var finishvalue = '1';
var checkitem = crmForm.ObjectId.replace(/[{,}]/g, "");
var xml = ""+
""+
"" +
"" +
"" +
"0" +
"MicrosoftCRM" +
"00000000-0000-0000-0000-000000000000" +
"" +
"" +
""+
""+
""+
""+ finishvalue + ""+
"" + checkitem + ""+ 
"" + ackn + ""+
""+
""+
""+
""+
"";
var xHReq = new ActiveXObject("Msxml2.XMLHTTP");
xHReq.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
xHReq.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/WebServices/Update");
xHReq.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xHReq.setRequestHeader("Content-Length", xml.length);
xHReq.send(xml);
var entityname = 'cgr_checklistpoints'
var sCode = '2'
var state = 'Inactive'
var xml = ""+
""+
"" +
"" +
"" +
"0" +
"MicrosoftCRM" +
"00000000-0000-0000-0000-000000000000" +
"" +
"" +
""+
""+
""+
"" + checkitem + ""+ 
""+ entityname + ""+ 
""+
""+ state + ""+ 
""+ sCode + ""+ 
""+ 
""+
""+
""+
"";
var xHReq = new ActiveXObject("Msxml2.XMLHTTP");
xHReq.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
xHReq.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/WebServices/Execute");
xHReq.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xHReq.setRequestHeader("Content-Length", xml.length);
xHReq.send(xml);
location.reload();
}
Reject = function() {
var ackn = '2';
var finishvalue = '1';
var checkitem = crmForm.ObjectId.replace(/[{,}]/g, "");;
var xml = ""+
""+
"" +
"" +
"" +
"0" +
// Change MicrosoftCRM for your Organization name here.
"MicrosoftCRM" +
"00000000-0000-0000-0000-000000000000" +
"" +
"" +
""+
""+
""+
""+ finishvalue + ""+
"" + checkitem + ""+ 
"" + ackn + ""+
""+
""+
""+ 
""+
"";
var xHReq = new ActiveXObject("Msxml2.XMLHTTP");
xHReq.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
xHReq.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/WebServices/Update");
xHReq.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xHReq.setRequestHeader("Content-Length", xml.length);
xHReq.send(xml);
var entityname = 'cgr_checklistpoints'
var sCode = '2'
var state = 'Inactive'
var xml = ""+
""+
"" +
"" +
"" +
"0" +
// Change MicrosoftCRM for your Organization name here.
"MicrosoftCRM" +
"00000000-0000-0000-0000-000000000000" +
"" +
"" +
""+
""+
""+
"" + checkitem + ""+ 
""+ entityname + ""+ 
""+
""+ state + ""+ 
""+ sCode + ""+ 
""+ 
""+
""+
""+
"";
var xHReq = new ActiveXObject("Msxml2.XMLHTTP");
xHReq.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
xHReq.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/WebServices/Execute");
xHReq.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xHReq.setRequestHeader("Content-Length", xml.length);
xHReq.send(xml);
location.reload();
}
RejectwC = function() {
var ackn = '3';
var comment = prompt("Bitte einen Grund angeben:", "Grund");
if(comment != null && comment != '') {
var finishvalue = '1';
var checkitem = crmForm.ObjectId.replace(/[{,}]/g, "");
var xml = ""+
""+
"" +
"" +
"" +
"0" +
// Change MicrosoftCRM for your Organization name here.
"MicrosoftCRM" +
"00000000-0000-0000-0000-000000000000" +
"" +
"" +
""+
""+
""+
"" + ackn + ""+ 
""+ comment + ""+
""+ finishvalue + ""+
""+ comment + ""+
"" + checkitem + ""+ 
""+
""+
""+
""+
"";
var xHReq = new ActiveXObject("Msxml2.XMLHTTP");
xHReq.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
xHReq.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/WebServices/Update");
xHReq.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xHReq.setRequestHeader("Content-Length", xml.length);
xHReq.send(xml);
var entityname = 'cgr_checklistpoints';
var sCode = '4';
var state = 'Inactive';
var xml = ""+
""+
"" +
"" +
"" +
"0" +
// Change MicrosoftCRM for your Organization name here.
"MicrosoftCRM" +
"00000000-0000-0000-0000-000000000000" +
"" +
"" +
""+ 
""+
""+
"" + checkitem + ""+
""+ entityname + ""+
""+ 
""+ state + ""+ 
""+ sCode + ""+ 
""+ 
""+
""+ 
""+
"";
var xHReq = new ActiveXObject("Msxml2.XMLHTTP");
xHReq.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
xHReq.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/WebServices/Execute");
xHReq.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xHReq.setRequestHeader("Content-Length", xml.length);
xHReq.send(xml);
}
location.reload();
}

var Spacer = {Right : 1, Left : 2, Both : 3, None : 4}
var Display = {Show : "inline", Hide : "none"}
if (crmForm.FormType == 4)
{
  //Configure Display when the form loads.
  ConfigureToolbarDisplay();

  //Configure the display each time a user manually changes the window width size.
  attachEvent("onresize",ConfigureToolbarDisplay);
}

function ConfigureToolbarDisplay()
{
  // use button title as input
  ShowHideToolbarButton("Mit ja bestätigen" , Spacer.Left, Display.Hide);
  ShowHideToolbarButton("Mit nein bestätigen" , Spacer.Left, Display.Hide);
  ShowHideToolbarButton("Ausgewählten Datensatz abweisen" , Spacer.Right, Display.Hide);
}  

function ShowHideToolbarButton(btnTitle , spacer , state)
{
  if(isNullOrEmpty(document.all.mnuBar1))
      return;
  if(isNullOrEmpty(btnTitle))
      return;
  if(isNullOrEmpty(spacer))
      spacer = ToolbarSpacer.None;
  if(isNullOrEmpty(state))
      state = ButtonDisplay.Hide;

  //Get all toolbar buttons
  var toolBarButtons = document.all.mnuBar1.rows[0].cells[0].childNodes[0].childNodes;

  //Loop through each button
  for (var i = 0 ; i < toolBarButtons.length ; i++)
  {
      var button = toolBarButtons[i];
      if(button.title.match(btnTitle) != null)
      {
          button.style.display = state;
          switch(spacer)
          {
              case Spacer.Right:
                  ShowHideSpacer(button.nextSibling);
                  break;
              case Spacer.Left:
                  ShowHideSpacer(button.previousSibling);
                  break;
              case Spacer.Both:
                  ShowHideSpacer(button.nextSibling);
                  ShowHideSpacer(button.previousSibling);
                  break;
          }
          return;
      }
  }

  function ShowHideSpacer(btnSpacer)
  {
      if(!isNullOrEmpty(btnSpacer))
      {
          btnSpacer.style.display = state;
      }
  }

  function isNullOrEmpty(obj)
  {
      return obj == null || typeof(obj) == "undefined" || obj == "";
  }
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, „Courier New“, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Das gesamte Script findet Ihr auch auf meinem SkyDrive.

Im Skript nutze ich auch einige Funktionen von Adi Katz, um Buttons im Grid auszublenden. Denn die Buttons sollten natürlich nicht mehr sichtbar sein, wenn die Checklistenpunkte bereits abgearbeitet / “archiviert” sind.

Grundsätzlich könnt Ihr eine Checklistenpunkt-Entität natürlich selbst designen. Damit der obige Code funktioniert, müssen lediglich folgende Attribute in Eurer Entität existieren:

checklist_3

Wenn Ihr diese Punkte berücksichtigt, habt Ihr die Möglichkeit verschiedene Checklistenpunkte aufzuführen.

In meinem Fall nutze ich Workflows, die mir zum Zeitpunkt der Erstellung eines Vorgangs entsprechende Checklistenpunkte an diesem erzeugt und somit zur Bearbeitung zur Verfügung stellt.

Ohne diese Punkte einzeln öffnen zu müssen, kann der Nutzer die Checkliste durchgehen und die einzelnen Punkte mit “Ja”, “Nein” oder “Abweisen” beantworten. Natürlich können die unterschiedlichen Stati wiederum weitere Checklistenpunkte erzeugen (wie gesagt mit den Workflows ist hier einiges zu machen).

Fehlt noch der die Erzeugung der ISV-Buttons. Dies geschieht über den Export der ISV-Config-Datei und Bearbeitung:

  <Entity name="cgr_checklistpoints">
          <MenuBar />
          <ToolBar ValidForCreate="0" ValidForUpdate="1">
            <Button Icon="/_imgs/ico_18_approve_y.gif" Client="Web,Outlook" JavaScript="Approve()">
              <Titles>
                <Title LCID="1033" Text="Approve" />
                <Title LCID="1031" Text="Ja" />
              </Titles>
              <ToolTips>
                <ToolTip LCID="1033" Text="Approve selected checklistitem" />
                <ToolTip LCID="1031" Text="Mit Ja bestätigen" />
              </ToolTips>
            </Button>
            <Button Icon="/_imgs/ico_18_approve_n.gif" Client="Web, Outlook" JavaScript="Reject()">
              <Titles>
                <Title LCID="1033" Text="Reject" />
                <Title LCID="1031" Text="Nein" />
              </Titles>
              <ToolTips>
                <ToolTip LCID="1033" Text="Reject selected checklistitem" />
                <ToolTip LCID="1031" Text="Mit nein bestätigen" />
              </ToolTips>
            </Button>
            <Button Icon="/_imgs/ico_18_reject.gif" Client="Web, Outlook" JavaScript="RejectwC()">
              <Titles>
                <Title LCID="1033" Text="Cancel" />
                <Title LCID="1031" Text="Abweisen" />
              </Titles>
              <ToolTips>
                <ToolTip LCID="1033" Text="Reject selected checklistitem" />
                <ToolTip LCID="1031" Text="Ausgewählten Datensatz abweisen" />
              </ToolTips>
            </Button>
            <ToolBarSpacer />
          </ToolBar>
          <Grid>
            <MenuBar>
              <ActionsMenu />
              <Buttons>
                <Button Client="Web, Outlook" Icon="/_imgs/ico_18_approve_y.gif" JavaScript="var ackn = '1';
                   var finishvalue = '1';
                   var checkitem = getSelected('crmGrid');
       for (var i = 0; i < checkitem.length; i++)
        {
        var xml = ""+ 
        ""+ 
        GenerateAuthenticationHeader()+ 
        ""+ 
        ""+ 
        ""+ 
        ""+ finishvalue + ""+ 
        "" + checkitem[i] + ""+ 
                            "" + ackn + ""+ 
                            ""+ 
        ""+ 
        ""+ 
        "";
        var xHReq = new ActiveXObject("Msxml2.XMLHTTP");
        xHReq.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
        xHReq.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/WebServices/Update");
        xHReq.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
        xHReq.setRequestHeader("Content-Length", xml.length);
        xHReq.send(xml);
        }
       var entityname = 'cgr_checklistpoints';
                   var sCode = '2';
                   var state = 'Inactive';
                   var checkitem = getSelected('crmGrid');
       for (var i = 0; i < checkitem.length; i++)
        {
        var xml = ""+ 
        ""+ 
        GenerateAuthenticationHeader()+ 
        ""+ 
        ""+ 
        ""+ 
        "" + checkitem[i] + ""+ 
        ""+ entityname + ""+ 
        ""+ 
        ""+ state + ""+ 
        ""+ sCode + ""+ 
        ""+ 
        ""+ 
        ""+ 
        "";
        var xHReq = new ActiveXObject("Msxml2.XMLHTTP");
        xHReq.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
        xHReq.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/WebServices/Execute");
        xHReq.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
        xHReq.setRequestHeader("Content-Length", xml.length);
        xHReq.send(xml);
        }
       crmGrid.Refresh();">
                  <Titles>
                    <Title LCID="1031" Text="Ja" />
                  </Titles>
                  <ToolTips>
                    <ToolTip LCID="1031" Text="Bestätigung des Checklistenpunktes mit Ja" />
                  </ToolTips>
                </Button>
                <Button Client="Web, Outlook" Icon="/_imgs/ico_18_approve_n.gif" JavaScript="var ackn = '2';
                   var finishvalue = '1';
                   var checkitem = getSelected('crmGrid');
       for (var i = 0; i < checkitem.length; i++)
        {
        var xml = ""+ 
        ""+ 
        GenerateAuthenticationHeader()+ 
        ""+ 
        ""+ 
        ""+ 
        ""+ finishvalue + ""+ 
        "" + checkitem[i] + ""+ 
                            "" + ackn + ""+ 
                            ""+ 
        ""+ 
        ""+ 
        "";
        var xHReq = new ActiveXObject("Msxml2.XMLHTTP");
        xHReq.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
        xHReq.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/WebServices/Update");
        xHReq.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
        xHReq.setRequestHeader("Content-Length", xml.length);
        xHReq.send(xml);
        }
       var entityname = 'cgr_checklistpoints';
                   var sCode = '2';
                   var state = 'Inactive';
                   var checkitem = getSelected('crmGrid');
       for (var i = 0; i < checkitem.length; i++)
        {
        var xml = ""+ 
        ""+ 
        GenerateAuthenticationHeader()+ 
        ""+ 
        ""+ 
        ""+ 
        "" + checkitem[i] + ""+ 
        ""+ entityname + ""+ 
        ""+ 
        ""+ state + ""+ 
        ""+ sCode + ""+ 
        ""+ 
        ""+ 
        ""+ 
        "";
        var xHReq = new ActiveXObject("Msxml2.XMLHTTP");
        xHReq.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
        xHReq.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/WebServices/Execute");
        xHReq.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
        xHReq.setRequestHeader("Content-Length", xml.length);
        xHReq.send(xml);
        }
       crmGrid.Refresh();">
                  <Titles>
                    <Title LCID="1031" Text="Nein" />
                  </Titles>
                  <ToolTips>
                    <ToolTip LCID="1031" Text="Bestätigung des Checklistenpunktes mit Nein" />
                  </ToolTips>
                </Button>
                <Button Client="Web, Outlook" Icon="/_imgs/ico_18_reject.gif" JavaScript="var ackn = '3';
                   var comment = prompt("Bitte einen Grund angeben:", "Grund");
                         if(comment != null && comment != '') {
                          var finishvalue = '1';
                   var checkitem = getSelected('crmGrid');
       for (var i = 0; i < checkitem.length; i++)
        {
        var xml = ""+ 
        ""+ 
        GenerateAuthenticationHeader()+ 
        ""+ 
        ""+ 
        ""+ 
        "" + ackn + ""+ 
                            ""+ comment + ""+ 
        ""+ finishvalue + ""+ 
        ""+ comment + ""+ 
        "" + checkitem[i] + ""+ 
                            ""+ 
        ""+ 
        ""+ 
        "";
        var xHReq = new ActiveXObject("Msxml2.XMLHTTP");
        xHReq.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
        xHReq.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/WebServices/Update");
        xHReq.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
        xHReq.setRequestHeader("Content-Length", xml.length);
        xHReq.send(xml);
        }
       var entityname = 'cgr_checklistpoints';
                   var sCode = '4';
                   var state = 'Inactive';
                   var checkitem = getSelected('crmGrid');
       for (var i = 0; i < checkitem.length; i++)
        {
        var xml = ""+ 
        ""+ 
        GenerateAuthenticationHeader()+ 
        ""+ 
        ""+ 
        ""+ 
        "" + checkitem[i] + ""+ 
        ""+ entityname + ""+ 
        ""+ 
        ""+ state + ""+ 
        ""+ sCode + ""+ 
        ""+ 
        ""+ 
        ""+ 
        "";
        var xHReq = new ActiveXObject("Msxml2.XMLHTTP");
        xHReq.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
        xHReq.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/WebServices/Execute");
        xHReq.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
        xHReq.setRequestHeader("Content-Length", xml.length);
        xHReq.send(xml);
        }}
       crmGrid.Refresh();">
                  <Titles>
                    <Title LCID="1031" Text="Abweisen" />
                  </Titles>
                  <ToolTips>
                    <ToolTip LCID="1031" Text="Abweisen des ausgewählten Checklistenpunktes" />
                  </ToolTips>
                </Button>
                <ToolBarSpacer />
              </Buttons>
            </MenuBar>
          </Grid>
        </Entity>

Ihr seht, dass ich den Grid-Code direkt in der ISV-Config Datei platziert habe. Damit bin ich nicht von der Öffnung der einzelnen Checklistenpunkte abhängig und kann direkt aus dem Grid Menü heraus die Punkte bearbeiten. Auch diesen Code Snippet findet Ihr auf meinem SkyDrive zur leichteren Bearbeitung.

checklist_4

Ein besonderer Punkt ist noch bei dem Button “Abweisen” integriert. Ein abgewiesener Checklistenpunkt muss begründet werden. Darum lasse ich ein IE Standard-Popup öffnen und den Nutzer einen Grund eintragen, der wiederum in dem Attribut eingefügt wird.

Noch ein paar Ansichten angepasst, den Checklistenpunkten ggfs. über eine weitere Entität noch Kategorien hinzugefügt und Ihr habt in Ansätzen bereits das, was Euch die Dialoge in der Version 2011 bieten werden.

Zugegeben, mit Hilfe der Dialoge werdet Ihr noch komplexere Prozesse aufsetzen können, z.B. Telefonskripte, doch am heutigen Beispiel wollte ich Euch aufzeigen, dass es auch mit der Version 4.0 bereits möglich ist, Prozesse im System abzubilden, denen eine Checkliste zu Grunde liegt.

Viel Spaß in der Umsetzung.

Technorati Tags:

Ein Gedanke zu “Microsoft Dynamics CRM 4.0 | Small Dialog Solution (Checklistitems)

  1. Pingback: Microsoft Dynamics CRM 2011 | Outlook 2010 Abstimmung-E-Mails « Microsoft Dynamics CRM & Co

Schreibe einen Kommentar

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s