5

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

Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
  • 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 Dec 31 '18 at 06:31
  • @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 Dec 31 '18 at 13:33

3 Answers3

3

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).

Lukas Nespor
  • 1,238
  • 1
  • 14
  • 22
  • Couldn't the GUID be fetched from the `UniqueId` column? – Szab Dec 31 '18 at 12:00
  • You stated that New Experience UI is enabled so I thought that you are using it. My solution is working only in New Experience. Client Side Rendering could be used for legacy UI. I will update my answer later. For now here are some samples https://code.msdn.microsoft.com/office/Client-side-rendering-JS-2ed3538a – Lukas Nespor Dec 31 '18 at 14:27
  • I am using the new experience. When I double-checked that list setting, it confirms this. However, I am beginning to think that because this is a view of the contents of a Document Set, that there are limitations. – Scott Marcus Dec 31 '18 at 16:48
  • *Because Document Set view is only in classic experience, it does not matter what is set in the settings (New or classic experience).* I tend to agree based on what I'm seeing, but do you have any documentation of this assertion? Also, is there a CSOM solution instead of a PowerShell one? I need to make my solution maintainable by someone down the line that may not be familiar with PowerShell. – Scott Marcus Jan 02 '19 at 21:33
  • Unfortunately not, just an observation. The PowerShell script is actually a CSOM, just called from PowerShell. Anyone who knows CSOM will know how to use it. – Lukas Nespor Jan 02 '19 at 21:40
  • Not necessarily. I'd be willing to use a pure JS CSOM solution without the PowerShell. – Scott Marcus Jan 02 '19 at 22:41
  • Your latest edit doesn't really make sense to me. Why is there an HTML for that needs to be filled out? And, why is there no loop to set the column for each item in the list? This is supposed to be a fully automated operation. Also, – Scott Marcus Jan 05 '19 at 00:16
  • I am making some progress on my own and now I can see that these solutions won't work because this is a document set and you must access the files in the document set, which is a different process than accessing items in a list. – Scott Marcus Jan 05 '19 at 04:20
  • Setting JSLink to field/column is one time operation. You don’t have to set anything for each item. It is dynamic rendering of a column/cell. It knows context of item and can access all its properties. I don’t know why it shouldn’t work because it works. Try it and you will see. Also read something about client side rendering https://code.msdn.microsoft.com/office/Client-side-rendering-JS-2ed3538a – Lukas Nespor Jan 05 '19 at 07:11
  • I'm sorry, I don't think you understand my use case. JS Link and CSR aren't appropriate here and not what I'm asking about. Also, you are showing how to set up a column's value in a regular list, not a document library that contains document sets. That is completely different code. – Scott Marcus Jan 05 '19 at 15:23
  • You want a column that contains link to start WF for each row in a view. My solution works in list and document library with document sets - of course I tried that. I won’t be posting answer that is not working. Oh, and everything is SPList underneath. As you can see SPDocumentLibrary derives from SPList https://learn.microsoft.com/en-us/previous-versions/office/sharepoint-server/ms460729%28v%3doffice.15%29 – Lukas Nespor Jan 05 '19 at 15:32
  • Your solution includes a form that someone needs to fill out and one of the fields in the form is the link to the workflow. The entire point of this post is to find a way to do this 100% automated. No forms to fill out, no user knowledge of what link to enter. Your code will add a link to the Document Set, not to each item within the document set. There's no way your code can do that as it is. All you are doing is accessing a list and a column. For Document Sets, you must go deeper. – Scott Marcus Jan 05 '19 at 16:47
  • My godness! You wanted JSOM solution, so I posted it. Look, the Client Side Rendering is used for change how the field is rendered to the user. The form takes name of a list and name of column that will be used for rendering the link. 3rd input is link to Javascript file that is responsible for rendering the link. It is not link to the WF! It is not setting anything for item rather it sets properties of the field definition in the list. You need to set it only once! Please look at the PowerShell or JSOM code what it really does. – Lukas Nespor Jan 05 '19 at 17:04
  • Yes, you've explained what your code does and I've explained that this is not what I'm asking for. There is no JavaScript file that is responsible for rendering the link. I've explained that my use case has a workflow produce that. Additionally, your code does not work with the document columns that are inside of a document set (and yes, I have tried your code). Thanks for your effort, but this is a solution to a problem that wasn't described. I'm simply looking for JSOM code that loops over the individual documents in a document set and writes a hyperlink that will be rendered as such. – Scott Marcus Jan 05 '19 at 17:11
0

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]/...)

Szab
  • 1,263
  • 8
  • 18
  • If you look at the URL and Source you will see that it is pointing to different list so, Source is required. – Lukas Nespor Dec 31 '18 at 12:06
  • It is only required for redirection purposes. The targeted list is referenced in the `List` query parameter. – Szab Dec 31 '18 at 12:10
  • I agree that it is only for redirection purpose. But the column with 'Request Change' is in different list than the workflow itself. So if you click the link and start the worklow you wodn't be redirected back to the first list. – Lukas Nespor Dec 31 '18 at 12:14
  • 1
    That's why I mentioned: _If you don't care about the return URL..._ – Szab Dec 31 '18 at 12:46
  • 1
    Thank you but as @LukášNešpor points out, I need the `Source` to redirect back to the list. Also there is no such column type as "Note", but as I've mentioned in my question, I tried your #2 suggestion with a "Multiple lines of text" and a "Full HTML content with formatting and constraints for publishing" field. In both cases the raw markup appeared, not a hyperlink. – Scott Marcus Dec 31 '18 at 14:15
0

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

Craig.Feied
  • 2,617
  • 2
  • 16
  • 25
  • Thanks but below the "Number of lines for editing" field, I don't have what you have. I have the column formatting with JSON option. This is because you are showing the "classic" experience configuration, but as I stated, I am using the "New Experience" configuration. – Scott Marcus Jan 01 '19 at 22:16
  • It's not really a matter of classic experience, but the Document Library. You can still turn Enhanced rich text option on using PowerShell. – Szab Jan 03 '19 at 09:30
  • @Szab I can't go with a PowerShell solution. It needs to be the CSOM with JS. – Scott Marcus Jan 05 '19 at 00:17