5
votes

My setup:

  • SharePoint Online (part of Office 365)
  • No access to server coded (.NET) solutions
  • Document Library using the Document Set content type
  • New Experience UI enabled

Use case:

I have a SP2013 Workflow that allows a user to make a change request for a document in the library. The workflow has Initiation Form Parameters and the data supplied for those parameters, along with a reference to the item that the workflow was run on are written to another list in the site. This all works just fine.

What I'm trying to do is create a column in the document library that allows a user to navigate to the workflow's Initiation Form directly instead of having to right-click on the item, choose "Advanced" and then "Workflows".

The link to the workflow's Initiation Form page (taken right out of the browser's address bar when manually navigating to it) in total looks like this (line breaks added for readability):

https://company.sharepoint.com/sites/ABC/wfsvc/e73969f753574a3bb30c8d3ce3ab9c56/WFInitForm.aspx

?List={f9b73015-1131-442d-95b8-9682149a27e6}

&ID=5

&ItemGuid={71AA92CE-2D37-4D43-B593-AB6004E9DCF0}

&TemplateID={64193686-AB59-4D44-B0EB-FBD8E2CB7A1F}

&WF4=1

&Source=https%3A%2F%2Fcompany%2Esharepoint%2Ecom%2Fsites%2FABC%2FCourseDocuments%2FForms%2FCourseDocuments%2Easpx%3FRootFolder%3D%252Fsites%252FDCU%252FCourseDocuments%252FBasic%2520Stuff%26FolderCTID%3D0x0120D52000E334520C326BA440BF6F86F3CA80AE2800E3DBD1BD3A1EA348A9D944A931464C4D

The ID and ItemGuid portions of the link will need to be dynamic as they will contain a reference to the specific library document that the workflow will need to run against. Everything else is static.

To dynamically produce this URL per each item, I've created a second workflow that is run when a new item in the library is added as well as being able to be run manually (for items already in the library) and that workflow does correctly produce the URL needed for each item.

The Problem:

This URL is longer than the 255 characters that the "Hyperlink or Picture" column accepts and so the workflow errors out when trying to write this URL to the column.

What I've Tried:

I've been at this a while now and found several posted work-arounds, none of which have worked:

  • I've tried shortening the URL by making it relative (and so the full site URL can be removed) and placing that in the "Hyperlink or Picture" field but that resulted in a workflow error of "Invalid URL" even though the URL produced works when copied and pasted into the address bar.
  • I've tried shortening the URL by encoding the static parts with Bitly and this time the workflow completed and wrote a clickable URL to the field, however while the static parts work individually, when they are concatenated with the other parts, the final URL leads to a 404 error at the Bitly site.
  • I've made a "Calculated" column that is set to "Date/Time" result and made the calculation be a concatenation of parts of the URL into an HTML hyperlink syntax (i.e. ="<a href='"&[column1]&[column2]&[column3]&"'>Click</a>"). While this did succeed in getting the entire thing produced and set into the library, with all the dynamic parts correct, the field doesn't render as parsed HTML, instead the full HTML markup is rendered, so it's not a clickable link. (The image below shows a relative URL, but with this approach, I used an absolute URL. The picture is meant to just show the result of markup being produced and not parsed.)

    enter image description here

  • I've tried adding the "Full HTML content with formatting and constraints for publishing" field to my library (with the SharePoint Server Publishing Infrastructure Site Feature enabled) and got the same HTML markup being displayed as with the calculated column attempt above.
  • I've tried using a "Multi-line" text field and gotten the same markup display as above as well.
  • According to this article, there is no length limit for encoded URLs, so I tried encoding the entire URL and placing that into a "Hyperlink or Picture" field, but the workflow errors out on that with an "Invalid URL" message.

So, the bottom line is that I can create the URL needed but cannot find a way to get it placed into a field for each item in a way that makes it clickable as an actual hyperlink.


UPDATE:

In response to @Lukáš Nešpor suggestion below, I have tried variations of that but followed your instructions and tried again. I don't get the option for Column Formatting in the list itself, but I do get that option when configuring the column in List Settings, so that's where I entered the JSON.

enter image description here enter image description here

But, when I try it, the JSON formatting doesn't work.

enter image description here

3
The maximum length of the SharePoint URL: The default value is 255, but you can define the maximum length between 1 and 400 characters. The length of a SharePoint Online URL must be between 1 and 400 characters. The length of SharePoint on-premises URL must be between 1 and 260 characters.Kousic
@Kousic You are talking about URLs and I am asking about columns. The maximum length of a hyperlink column is 255. When I try to use other column types that do allow for longer character counts, I can populate the field, but it doesn't display as a clickable hyperlink.Scott Marcus

3 Answers

3
votes

New user experience (in general)

You could leverage column formatting. It can be used in modern lists to change how the column (field) is rendered. One possible use is to render a link with properties of current item. Almost all fields can be referenced including ID, but GUID unfortunately not.

To resolve issue with GUID field (witn no-code), you could create text column in the list and call it e.g. Log Change Request. Then create simple Workflow and set this newly created column to current item's GUID. Don't forget to set the workflow to run when new item is created.

enter image description here

Then go to the list (using modern experience) and set column format.

enter image description here

Pane on the right will open. Paste bellow JSON to the field and save changes.

{
  "$schema": "https://developer.microsoft.com/json-schemas/sp/column-formatting.schema.json",
  "elmType": "a",
  "txtContent": "Link",
  "attributes": {
    "href": {
      "operator": "+",
      "operands": [
        "https://company.sharepoint.com/sites/ABC/wfsvc/e73969f753574a3bb30c8d3ce3ab9c56/WFInitForm.aspx",
        "?List={f9b73015-1131-442d-95b8-9682149a27e6}",
        "&ID=",
        "[$ID]",
        "&ItemGuid=",
        "@currentField",
        "&TemplateID={64193686-AB59-4D44-B0EB-FBD8E2CB7A1F}",
        "&WF4=1",
        "&Source=https%3A%2F%2Fcompany%2Esharepoint%2Ecom%2Fsites%2FABC%2FCourseDocuments%2FForms%2FCourseDocuments%2Easpx%3FRootFolder%3D%252Fsites%252FDCU%252FCourseDocuments%252FBasic%2520Stuff%26FolderCTID%3D0x0120D52000E334520C326BA440BF6F86F3CA80AE2800E3DBD1BD3A1EA348A9D944A931464C4D"
      ]
    }
  }
}

Create item and when the Workflow finish, the column should contain the link you need.


Classic experience

For classic (legacy) view can be used Client Side Rendering. It do the same as column formatting in new experience.

Create text column and call it e.g. Log Change Request. Next step is to create Javascript file upload it to SharePoint (somewehere) and register this javascript as JSLink to the column.

1) Create Javascript file and call it e.g. log-change-request.js

// CSR-override for MDS enabled site
RegisterModuleInit("~site/SiteAssets/log-change-request.js", RegisterLink);

// CSR-override for MDS disabled site
RegisterLink(); 

function RegisterLink() {
  var field = {};
  field.Templates = {};
  field.Templates.Fields = {
    "LogChangeRequest": {
      "View": fieldTemplate
    }
  };

  SPClientTemplates.TemplateManager.RegisterTemplateOverrides(field);
}

function fieldTemplate(context) {
  var item = context.CurrentItem;
  return "<a href='"
    + "https://company.sharepoint.com/sites/ABC/wfsvc/e73969f753574a3bb30c8d3ce3ab9c56/WFInitForm.aspx"
    + "?List={f9b73015-1131-442d-95b8-9682149a27e6}"
    + "&ID=" + item.ID
    + "&ItemGuid=" + item.UniqueId
    + "&TemplateID={64193686-AB59-4D44-B0EB-FBD8E2CB7A1F}"
    + "&WF4=1"
    + "&Source=https%3A%2F%2Fcompany%2Esharepoint%2Ecom%2Fsites%2FABC%2FCourseDocuments%2FForms%2FCourseDocuments%2Easpx%3FRootFolder%3D%252Fsites%252FDCU%252FCourseDocuments%252FBasic%2520Stuff%26FolderCTID%3D0x0120D52000E334520C326BA440BF6F86F3CA80AE2800E3DBD1BD3A1EA348A9D944A931464C4D"
    + "'>"
    + "Link"
    + "</a>";
}

2) Upload this file to Site Assets to the site collection where you created the column Log Change Request. Note: this file can be placed anywhere you just have to change the path in it.
3) Download an install SharePoint Online Client Components SDK. It will copy some DLLs that are needed to connect to the SharePoint using PowerShell.
4) Run PowerShell script bellow which will set JSLink property of the column to the path to the Javascript file.

.NET CSOM solution how to set the column

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client")
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime")

function Set-JSLink() {
  Param(
    [string]$SiteUrl,
    [string]$ListTitle,
    [string]$ColumnTitle,
    [string]$JSLinkUrl
  )

  $creds = Get-Credential

  $ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteUrl)
  $ctx.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($creds.UserName, $creds.Password)

  $list = $ctx.Web.Lists.GetByTitle($ListTitle)
  $ctx.Load($list)
  $ctx.ExecuteQuery()

  $column = $list.Fields.GetByTitle($ColumnTitle)
  $column.JSLink = $JSLinkUrl
  # Make it read only so it is not visible in new or edit form
  $column.ReadOnlyField = $true
  $column.Update()

  $ctx.ExecuteQuery()
  $ctx.Dispose()
}

# Example:
Set-JSLink -SiteUrl "https://tenant.sharepoint.com/sites/ABC" -ListTitle "Document Sets" -ColumnTitle "Log Change Request" -JSLinkUrl "~site/SiteAssets/log-change-request.js"

JSOM solution how to set the column
Using this aproach does not require to install any SDK. Just place this HTML code to Script Editor.

<form>
  <input type="text" id="listTitle" placeholder="List title" /><br />
  <input type="text" id="columnTitle" placeholder="Column title" /><br />
  <input type="text" id="jsLink" placeholder="JSLink Url" /><br />
  <button onclick="setColumn(); return false;">Configure column</button>
</form>

<script type="text/javascript">
  'use strict';
  SP.SOD.executeFunc("sp.js")

  function setColumn() {
    var listTitle = document.getElementById("listTitle").value;
    var columnTitle = document.getElementById("columnTitle").value;
    var jsLink = document.getElementById("jsLink").value;

    var cc = new SP.ClientContext()
    var list = cc.get_web().get_lists().getByTitle(listTitle);
    cc.load(list);
    cc.executeQueryAsync(
      function () {
        var column = list.get_fields().getByTitle(columnTitle);
        column.set_jsLink(jsLink);
        column.set_readOnlyField(true);
        column.update();

        cc.executeQueryAsync(
          function () {
            alert("Column sucessfuly configured");
          },
          function (sender, args) {
            console.error(args.get_message());
          }
        );
      },
      function (sender, args) {
        console.error(args.get_message());
      }
    );

    cc.dispose();
  }

</script>

5) Open some Document Set, add document and the column should contain the link you need.

Note:

Because Document Set view is only in classic experience, it does not matter what is set in the settings (New or classic experience).

0
votes

Two things you can try:

  1. The Source query string parameter is taking about half of your URL. If you don't care about the return URL, then this whole section can most likely be safely deleted, which will cause your string to fit within the 255 characters limitation of the standard URL field.
  2. Create a note field with HTML support enabled (when creating it from the UI, you will have to select the Enhanced rich text (Rich text with pictures, tables, and hyperlinks) option in the additional column settings) and then use this field to store your markup (the <a href="...">...</a> element HTML). If set up correctly, your markup will be properly rendered both in the list view and on list item forms.

Also, as the link can be displayed in many places (such as list views, list view webparts, list item forms) avoid using the relative URL - while the ../wfsvc/[wf_id]/... URL might be correct in, for example, list view context, it will be incorrect in the list item form context. Use absolute URLs or web server relative URLs instead (such as /sites/yoursite/wfsvc/[wf_id]/...)

0
votes

The Multi-Line Text field was intended as the solution for the "long URL" requirement.

By default the Multi-Line Text field handles only plain text, rather than rich text or enhanced rich text. Changing this setting (if available to you) will cause your hyperlink to be rendered as a hyperlink, and you won't be subject to the 255 character limit that applies to hyperlink columns.

In Designer you can go to Customization -> Edit Columns and edit your Multi-Line text column, then check the checkbox for Rich text or Enhanced rich text.

For Sharepoint Online you select the column in List Settings or Library Settings and set the radio button for Rich Text or Enhanced rich text.

For "New Experience" it is not possible to format text as Rich Text. You can still format text as Enhanced Rich Text, but HTML tags are not handled (WTF??). Of course you can switch a list or library back to classic experience within the overall New Experience site, and that will give you back Rich Text.

MSFT has a backlog item to add Multiline Rich Text Support for NE, but in my time at MSFT I never encountered any reasonable prioritization for this kind of nasty little gap, so no saying when it might get fixed.

enter image description here