Precedentemente avevo già fatto un post per SharePoint onprem su questo tema, ma purtroppo non è applicabile a SharePoint Online.

Lo scopo è visualizzare sulla riga della lista sharepoint direttamente gli allegati (attachments) in modo che siano raggiungibili e visualizzabili senza andare in view/edit dell'item.
Lista sharepoint con allegati
Lista sharepoint con allegati

Per raggiungere lo scopo servono 3 elementi:

Choice multipla

Il campo Links di tipo choice a scelta multipla, ci servirà per memorizzare, tramite il flow Power Automate, le url degli allegati che poi verranno visualizzati tramite un Column formatting.
Impostazione campo choice
Impostazione campo choice
I campo può essere impostato come hidden non dovrà essere modificato dall'utente.

Power Automate

Il flusso Power Automate ha un trigger che lo farà partire ad ogni cambiamento dell'item.
Le attività che svolge sono:
  • elencare gli allegati presenti dell'item
  • verificare se il nuovo valore è diverso dal precedente
  • salvare le url degli allegati nel campo Links (choice multipla)
  • ridurre il retriggering
Flow
Flow

Di seguito le impostazioni principali.

Recupero i campi che sono stati modificati

Power Automate: Get changes for an item or a file (properties only)

{
  "type": "OpenApiConnection",
  "inputs": {
    "parameters": {
      "dataset": "@variables('VarSiteUrl')",
      "table": "@variables('VarListId')",
      "id": "@triggerBody()?['ID']",
      "since": "@triggerBody()?['{TriggerWindowStartToken}']",
      "includeDrafts": false,
      "until": "@triggerBody()?['{TriggerWindowEndToken}']"
    },
    ...
}

Verifica che il campo modificato non sia Links in questo casi si tratta di un retriggering causato dal flow, evito la ricorrenza infinita

Power Automate: Condition: Links changed (self update)

{
  "type": "If",
  "expression": {
    "and": [
      {
        "equals": [
          "@body('Get_changes_for_an_item_or_a_file_(properties_only)')?['ColumnHasChanged/Links']",
          "@true"
        ]
      }
    ]
  },
...
}

Leggo gli allegati dell'item

Power Automate: Send an HTTP: Get Attachments

{
  "type": "OpenApiConnection",
  "inputs": {
    "parameters": {
      "dataset": "@variables('VarSiteUrl')",
      "parameters/method": "GET",
      "parameters/uri": "_api/web/lists('@{variables('VarListId')}')/items(@{triggerBody()?['ID']})/AttachmentFiles?$select=ServerRelativeUrl&$orderbt=ServerRelativeUrl",
      "parameters/headers": {
        "accept": "application/json;odata=nometadata"
      }
    },
    ..
}

Creo un array con solo le url (è il formato che serve per aggiornare il campo Links)

Power Automate: Select New AbsoluteUri

{
  "type": "Select",
  "inputs": {
    "from": "@body('Send_an_HTTP:_Get_Attachments')?['value']",
    "select": "@item()?['ServerRelativeUrl']"
  },
  ...
}
esempio di output

JSON

{
    "body": [
        "/sites/SitoITA/Lists/ListAttachments/Attachments/2/diablo.jpg",
        "/sites/SitoITA/Lists/ListAttachments/Attachments/2/DSCN1655.JPG",
        "/sites/SitoITA/Lists/ListAttachments/Attachments/2/DSCN2884.JPG"
    ]
}

Trasformo l'array precedente in una stringa concatenata con delle | (pipe), servirà poi per verificare se il valore è cambiato

Power Automate: Join New AbsoluteUri

{
  "type": "Join",
  "inputs": {
    "from": "@body('Select_New_AbsoluteUri')",
    "joinWith": "|"
  },
  ...
}
esempio di output

JSON

{
    "body": "/sites/SitoITA/Lists/ListAttachments/Attachments/2/diablo.jpg|/sites/SitoITA/Lists/ListAttachments/Attachments/2/DSCN1655.JPG|/sites/SitoITA/Lists/ListAttachments/Attachments/2/DSCN2884.JPG"
}

Trasformo il valore attuale del capo Link in un array di stringhe

Power Automate: Select Actual AbsoluteUri

{
  "type": "Select",
  "inputs": {
    "from": "@triggerBody()?['Links']",
    "select": "@item()?['Value']"
  },
  "...
}
esempio di output

JSON

{
    "body": [
        "/sites/SitoITA/Lists/ListAttachments/Attachments/2/diablo.jpg",
        "/sites/SitoITA/Lists/ListAttachments/Attachments/2/DSCN1655.JPG",
        "/sites/SitoITA/Lists/ListAttachments/Attachments/2/DSCN2884.JPG",
        "/sites/SitoITA/Lists/ListAttachments/Attachments/2/img2.png"
    ]
}

Come prima trasformo in stringa il valore attuale per il confronto

Power Automate: Join Actual AbsoluteUri

{
  "type": "Join",
  "inputs": {
    "from": "@body('Select_Actual_AbsoluteUri')",
    "joinWith": "|"
  },
  ...
}

Con questa condizione evito di scrivere il valore se non è cambiato

Power Automate: Condition: value changed

{
  "type": "If",
  "expression": {
    "and": [
      {
        "not": {
          "equals": [
            "@body('Join_Actual_AbsoluteUri')",
            "@body('Join_New_AbsoluteUri')"
          ]
        }
      }
    ]
  },
  ...
}

Se il valore è cambiato, lo salvo

Power Automate: Send an HTTP update Links value

{
  "type": "OpenApiConnection",
  "inputs": {
    "parameters": {
      "dataset": "@variables('VarSiteUrl')",
      "parameters/method": "PATCH",
      "parameters/uri": "_api/web/lists('@{variables('VarListId')}')/items(@{triggerBody()?['ID']})",
      "parameters/headers": {
        "accept": "application/json;odata=nometadata",
        "content-type": "application/json",
        "if-match": "*"
      },
      "parameters/body": "{\n  \"Links\":  @{body('Select_New_AbsoluteUri')}\n}"
    },
    ...
}

Column formatting

Il Column formatting serve per visualizzare sull'item della lista la preview delle immagini e i link degli allegati che non sono immagini

JSON

{
  "$schema": "https://developer.microsoft.com/json-schemas/sp/v2/column-formatting.schema.json",
  "elmType": "div",
  "style": {
    "display": "flex",
    "flex-direction": "row",
    "flex-wrap": "wrap"
  },
  "children": [
    {
      "elmType": "div",
      "forEach": "imgUrl in @currentField",
      "children": [
        {
          "elmType": "a",
          "attributes": {
            "class": "ms-Link ms-fontColor-themePrimary",
            "target": "_blank",
            "href": "=[$imgUrl]+'?web=1'",
            "title": "Allegato"
          },
          "children": [
            {
              "elmType": "img",
              "attributes": {
                "src": "[$imgUrl]",
                "alt": "Immagine"
              },
              "style": {
                "display": "=if(endsWith(toLowerCase([$imgUrl]),'.gif') || endsWith(toLowerCase([$imgUrl]),'.png') || endsWith(toLowerCase([$imgUrl]),'.jpg') || endsWith(toLowerCase([$imgUrl]),'.jpeg'), 'block', 'none')",
                "width": "100px",
                "height": "auto",
                "margin": "5px"
              }
            },
            {
              "elmType": "span",
              "style": {
                "display": "=if(endsWith(toLowerCase([$imgUrl]),'.gif') || endsWith(toLowerCase([$imgUrl]),'.png') || endsWith(toLowerCase([$imgUrl]),'.jpg') || endsWith(toLowerCase([$imgUrl]),'.jpeg'), 'none', 'block')",
                "margin": "5px"
              },
              "txtContent": "='◼ ' + substring([$imgUrl], lastIndexOf([$imgUrl], '/')+1, 4000)"
            }
          ]
        }
      ]
    }
  ]
}

Esecuzione

Ad ogni cambiamento si avranno fino a 2 esecuzioni del flow.
La prima si verifica ad ogni cambiamento dell'item e verrà registrato come stato Succeded.
Nel caso venisse aggiornato il campo Links con un nuovo valore, si noterà una seconda esecuzione son stato Cancelled (vedi action Condition: Links changed (self update))
run history
run history