Blog

PowerApps Functions

On 30/09/2022

PowerApps functions

Parse text to number

    Filter('Workflow Tasks'; ID = Value(txtId.Text))

Add datas (listItem)

    Patch(NewVoie;Defaults(NewVoie);{Num_x00e9_rovoie:"0"&LookUp(NewVoie;ID=1).Num_x00e9_rovoie}))

Update context, and forms datas

    SubmitForm(FormBeneficiaires);;ResetForm(FormBeneficiaires);; NewForm(FormBeneficiaires);; UpdateContext({showPopup:false});

        If(IsBlankOrError(SubmitForm(Form1)), Set(saveStatus, "An error occured" & Form1.Error), Set(saveStatus, "Operation succeded"))

Navigate to another form

    Navigate(Page_infos_enregistrements)

Get query string parameter and set a variable

    Set(InitiativeId; Param("ID"))

Getquerystringparam

 

Get a field from your datasource by ID

    First(Filter(Initiatives; ID=1)).Nom

 

And Or Not

Or(And(Radio1.Selected.Value=4; !IsBlank(txtComment.Text));Radio1.Selected.Value<4)

 

Update Lookup Field

Patch(
        ResultatAnalyses;
        First(//here item to update
            Filter(
                ResultatAnalyses;
                Affaire.Id = currentAffaire.ID And Analyse.Id = ThisItem.ID
            )
        );
        {
            Title: "notused";
            Commentaires: txtGalComment.Text;
            Gravite: Rating1.Value;
            Affaire: {//lookup field name
                Id: currentAffaire.ID;//id of lookup
                Value: LookUp(
                    Affaires;//list who contains lookup value
                    ID = currentAffaire.ID;//id of lookup
                    currentAffaire.Title//title of lookup value
                )
            }
        }
    )

Patch Choice

TypeIntervention: {Value: dtvTypeIntervention.Selected.Value}

Execute automate with json

'My workflow'.Run(
	JSON(
		{
			SolutionId: selectedSolution.ID,
			ImageContent: UploadedImage14.Image
		},
		JSONFormat.IncludeBinaryData
	)
);

Reg ex to get cleaned string

Clear(AttachmentsCollection);
ForAll(
      RenameColumns(DataCardValue91.Attachments, "Name", "Name1"),
      Collect(
             AttachmentsCollection,
             Name1
      )
);Set(Title1, First(AttachmentsCollection).Value);Set(FileName1, Concat( Split(First(AttachmentsCollection).Value, "" ), If( IsMatch(Result, "([^A-Za-z0-9\.\-])" ), "",Result ) ))

Save Form

SubmitForm(Form1);;If(!IsBlankOrError( Form1.Error); Notify("Une erreur est survenue lors de la sauvegarde " & Form1.Error; NotificationType.Error);Notify("La savegarde a réussi";NotificationType.Information);;Set(currentElement; Form1.LastSubmit))

 

Sort columns


Set(Month, Distinct(SortByColumns(CurrentMonthMails, "Year", Ascending, "Month", Ascending), Month))

Set date


Set(StartDate, DateAdd(DateTimeValue( Day(Today) &"/"& Month(Today) &"/"& Year(Today) &" 00:00:00"), -30));

Sum


Sum(Filter(CurrentMonthMails, Month = ThisItem.Result ), uniqMails)

 

Sharepoint Rest Get User ID By Mail

On 23/06/2025



async function GetDigestValue(siteUrl) {//
    const fetchOptions = {
        method: 'POST',
        headers: {
            'Accept': 'application/json;odata=verbose',
            'Content-type': 'application/json;odata=verbose'
        }
    };

    const response = await fetch(siteUrl + "/_api/contextinfo", fetchOptions);
    return (await response.json()).d.GetContextWebInformation.FormDigestValue;
}




async function EnsureUser(siteUrl, userEmail) {
    const digest = await GetDigestValue(siteUrl);
    console.log("digest", digest);

    const body = {
        'logonName': `i:0#.f|membership|${userEmail}`
    }
    const response = await fetch(`${siteUrl}/_api/web/ensureuser?$select=Id`, {
        method: "POST",
        headers: {
            "Accept": "application/json;odata=verbose",
            "Content-Type": "application/json;odata=verbose",
            "X-RequestDigest": digest
        },
        body: JSON.stringify({
            'logonName': `i:0#.f|membership|${userEmail}`
        })
    });
    console.log("response", response);
    const userData = await response.json();
    return userData.d.Id;
}

async function getUserIdByEmail(siteUrl, userEmail) {
    try {

        const fetchOptions = {
            method: 'GET',
            headers: {
                'Accept': 'application/json;odata=verbose',
                'Content-type': 'application/json;odata=verbose'
            }
        };

        const response = await fetch(siteUrl + `/_api/web/siteusers/getbyemail('${encodeURIComponent(userEmail)}')`, fetchOptions);
        const data = await response.json();
        console.log("getUserByEmail data", data);
        return data.d.Id;
    } catch (error) {
        console.log("getUserByEmail Error", error);
        return null;
    }
}
let siteUrl1 = "https://eutelsatgroup.sharepoint.com/sites/fdiSandBox";
let email1 = "ffdietrich-ext@eutelsat.com";
let ret = await EnsureUser(siteUrl1, email1);


console.log("response", ret);
const siteUrl = "https://test.sharepoint.com/sites/Dev_wf";
const email = "fpalmo@test.com";
console.log("response", ret0); 
const ret = await EnsureUser(siteUrl, email);

const ret0 = await getUserIdByEmail(siteUrl, email);



console.log("response", ret);

Show Lists Roleassignments

On 27/05/2025



// Fonction pour récupérer tous les RoleDefinitionBindings
async function getRoleDefinitionBindings(list, Id, Title, ServerRelativeUrl, ItemsCount, Hidden, HasUniqueRoleAssignments) {

    let p = `vdfvd`;//$${apiGet}
    const getPai = `${list}/roleassignments?$expand=Member/users,RoleDefinitionBindings`;
    console.log("request", getPai);
    const response = await fetch(getPai, {
        method: 'GET',
        headers: {
            'Accept': 'application/json;odata=verbose'
        }
    });
    const data = await response.json();
    data.d.results;
    console.log(data.d.results);

    const ret = [];
    for (let i = 0; i < data.d.results.length; i++) {
        var perm = data.d.results[i];

        const toAdd = {};
        toAdd.ListId = Id;
        toAdd.ListTitle = Title;
        toAdd.ListServerRelativeUrl = ServerRelativeUrl;
        toAdd.ItemsCount = ItemsCount;
        toAdd.Hidden = Hidden;
        toAdd.HasUniqueRoleAssignments = HasUniqueRoleAssignments;
        toAdd.Id = perm.Member.Id;
        toAdd.LoginName = perm.Member.LoginName;
        toAdd.Email = perm.Member.Email ?? "";
        toAdd.Description = perm.Member.Description;
        toAdd.Title = perm.Member.Title;
        toAdd.IsHiddenInUI = perm.Member.IsHiddenInUI;
        toAdd.PrincipalId = perm.Member.PrincipalId;
        toAdd.PrincipalType = perm.Member.PrincipalType;
        //users bu group
        if (perm.Member.Users !== undefined && perm.Member.Users !== null && perm.Member.Users.results.length > 0) {
            toAdd.Users = [];
            for (let j = 0; j < perm.Member.Users.results.length; j++) {
                const u = perm.Member.Users.results[j];
                toAdd.Users.push({
                    Email: u.Email,
                    Id: u.Id,
                    Title: u.Title,
                    UserPrincipalName: u.UserPrincipalName,
                    IsSiteAdmin: u.IsSiteAdmin,
                    IsShareByEmailGuestUser: u.IsShareByEmailGuestUser
                });
            }
        }
        toAdd.RoleDefinitionBindings = ""
        if (perm.RoleDefinitionBindings !== undefined && perm.RoleDefinitionBindings !== null && perm.RoleDefinitionBindings.results.length > 0) {

            for (let j = 0; j < 1; j++) {
                const r = perm.RoleDefinitionBindings.results[j];
                toAdd.RoleDefinitionBindings = r.Name;
            }
        }
        ret.push(toAdd);
    }
    
    console.log(ret);
    return ret;
}

let url = "https://test.sharepoint.com/sites/csc";


let lists = `${url}/_api/web/lists?$select=Hidden,Title,RootFolder/ServerRelativeUrl,Id,ItemCount,HasUniqueRoleAssignments&$expand=RootFolder`;//&$filter=Hidden eq false
let response = await fetch(lists, {
    method: 'GET',
    headers: {
        'Accept': 'application/json;odata=verbose'
    }
});
let data = await response.json();


let datas = [];
for (let z = 0; z < data.d.results.length; z++) {//
    const lst = data.d.results[z];
    console.log("lst", lst);
    const datas1 = await getRoleDefinitionBindings(`${url}/_api/web/lists(guid'${lst.Id}')`, lst.Id, lst.Title, lst.RootFolder.ServerRelativeUrl, lst.ItemCount, lst.Hidden, lst.HasUniqueRoleAssignments);
    
    console.log(datas1);
    for (let u = 0; u < datas1.length; u++) {
        datas.push(datas1[u]);
    }
}

console.log("datas", datas);

let csv = "ListId;ListTitle;ListServerRelativeUrl;ItemsCount;Hidden;HasUniqueRoleAssignments;MemberTitle;MemberEmail;MemberLoginName;MemberId;MemberDescription;Permission;TopLevel;UserMail;UserTitle;UserId;UserUserPrincipalName;IsSiteAdmin;IsShareByEmailGuestUser\n";
for (let k = 0; k < datas.length; k++) {
    const d = datas[k];
    let member = "";
    member += `${d.ListId};`
    member += `${d.ListTitle};`
    member += `${d.ListServerRelativeUrl};`
    member += `${d.ItemsCount};`
    member += `${d.Hidden};`
    member += `${d.HasUniqueRoleAssignments};`
    member += `${d.Title};`
    member += `${d.Email};`
    member += `${d.LoginName};`
    member += `${d.Id};`
    member += `${d.Description ?? ""};`
    member += `${d.RoleDefinitionBindings};`
    csv += `${member}true;;;;;;\n`;
    //debugger;
    if (d.Users !== undefined) {
        for (let j = 0; j < d.Users.length; j++) {
            const user = d.Users[j];
            let u = `${member}false;`;
            u += `${user.Email};`;
            u += `${user.Title};`;
            u += `${user.Id};`;
            u += `${user.UserPrincipalName ?? ""};`;
            u += `${user.IsSiteAdmin};`;
            u += `${user.IsShareByEmailGuestUser}`;
            csv += `${u}\n`
        }
    }
}
console.log(csv);

Get Web Role Assignments

On 27/05/2025



// Fonction pour récupérer tous les RoleDefinitionBindings
async function getRoleDefinitionBindings(apiGet, type) {

    let p = `vdfvd`;//$${apiGet}
    const getPai = `${apiGet}/roleassignments?$expand=Member/users,RoleDefinitionBindings`;
    const response = await fetch(getPai, {
        method: 'GET',
        headers: {
            'Accept': 'application/json;odata=verbose'
        }
    });
    const data = await response.json();
    data.d.results;
    console.log(data.d.results);

    const ret = [];
    for (let i = 0; i < data.d.results.length; i++) {
        var perm = data.d.results[i];

        const toAdd = {};
        toAdd.type = type;
        toAdd.Id = perm.Member.Id;
        toAdd.LoginName = perm.Member.LoginName;
        toAdd.Email = perm.Member.Email ?? "";
        toAdd.Description = perm.Member.Description;
        toAdd.Title = perm.Member.Title;
        toAdd.IsHiddenInUI = perm.Member.IsHiddenInUI;
        toAdd.PrincipalId = perm.Member.PrincipalId;
        toAdd.PrincipalType = perm.Member.PrincipalType;
        //users bu group
        if (perm.Member.Users !== undefined && perm.Member.Users !== null && perm.Member.Users.results.length > 0) {
            toAdd.Users = [];
            for (let j = 0; j < perm.Member.Users.results.length; j++) {
                const u = perm.Member.Users.results[j];
                toAdd.Users.push({
                    Email: u.Email,
                    Id: u.Id,
                    Title: u.Title,
                    UserPrincipalName: u.UserPrincipalName,
                    IsSiteAdmin: u.IsSiteAdmin,
                    IsShareByEmailGuestUser: u.IsShareByEmailGuestUser
                });
            }
        }
        //debugger;
        // = [];
        toAdd.RoleDefinitionBindings = ""
        if (perm.RoleDefinitionBindings !== undefined && perm.RoleDefinitionBindings !== null && perm.RoleDefinitionBindings.results.length > 0) {

            for (let j = 0; j < 1; j++) {
                const r = perm.RoleDefinitionBindings.results[j];
                toAdd.RoleDefinitionBindings = r.Name;
                // toAdd.RoleDefinitionBindings = {
                //     Name: r.Name,
                //     Hidden: r.Hidden,
                //     Description: r.Description,
                //     RoleTypeKind: r.RoleTypeKind,
                //     Order: r.Order
                // };

            }
        }
        ret.push(toAdd);

    }
    console.dir("ret", ret);
    console.log(ret);
    return ret;
}

let url = "https://test.sharepoint.com/sites/csc";
debugger;
const datas = await getRoleDefinitionBindings(`${url}/_api/web`, "SiteCollection");


let csv = "type;MemberTitle;MemberEmail;MemberLoginName;MemberId;MemberDescription;Permission;TopLevel;UserMail;UserTitle;UserId;UserUserPrincipalName;IsSiteAdmin;IsShareByEmailGuestUser\n";
for (let k = 0; k < datas.length; k++) {
    const d = datas[k];
    let member = "";
    member += `${d.type};`
    member += `${d.Title};`
    member += `${d.Email};`
    member += `${d.LoginName};`
    member += `${d.Id};`
    member += `${d.Description ?? ""};`
    member += `${d.RoleDefinitionBindings};`
    csv += `${member}true;;;;;;\n`;
    //debugger;
    if (d.Users !== undefined) {
        for (let j = 0; j < d.Users.length; j++) {
            const user = d.Users[j];
            let u = `${member}false;`;
            u += `${user.Email};`;
            u += `${user.Title};`;
            u += `${user.Id};`;
            u += `${user.UserPrincipalName ?? ""};`;
            u += `${user.IsSiteAdmin};`;
            u += `${user.IsShareByEmailGuestUser}`;
            csv += `${u}\n`
        }
    }
}
console.log(csv);

PowerShell Compaire Property Items

On 26/05/2025


$ret1 = "PO-REQ-..2101.docx"
# $ret2 = "PO-RE..-2101.pdf"

$url1 = "https://test.sharepoint.com/sites/test/procedures";

$url2 = "https://test.sharepoint.com/sites/test/procedures"
Clear-Host
function ToPdf {
    param($fileName)

    $paths = $fileName.Split(".")
    if ($paths.Count -eq 2) {
        return "$($paths[0]).pdf"
    }
    if ($paths.Count -gt 2) {
        $ret = "";
        for ($i = 0 ; $i -lt $paths.Count - 1 ; $i++) {
            $ret += "$($paths[$i])" + "."
        }
        $ret += "pdf"
        return $ret
    }
    throw "Error : $($fileName)"
}



$list = "Work Instructions - Sources"
$list2 = "Work Instructions"
$ColumnsToCompaire = "Csc_Domain"
$ColumnRef = ""
$select = "Title,FileLeafRef,Csc_Domain,FileDirRef"

$buildSelet = ""
foreach ($col in ($select -split ",")) {
    $buildSelet += ""
}
$buildSelet += ""
$con1 = Connect-PnPOnline -Url $url1 -ReturnConnection -UseWebLogin
$con2 = Connect-PnPOnline -Url $url2 -ReturnConnection -UseWebLogin

$list1 = Get-PnPList -Identity $list -Connection $con1
Write-Host "list 1 : $($list1.ItemCount)"

$query = "<View Scope='RecursiveAll'><RowLimit>1000</RowLimit><OrderBy><FieldRef Name='Modified' Ascending='FALSE' /></OrderBy><Query><Where><Neq><FieldRef Name='FSObjType' /><Value Type='Integer'>1</Value></Neq></Where></Query>$($select)</View>"
$items1 = Get-PnPListItem -List $list -Connection $con1 -Query $query
$items2 = Get-PnPListItem -List $list2 -Connection $con2 -Query $query 

foreach ($item in $items1) {
    if ("$($item[$ColumnsToCompaire] )".Trim().ToLower() -eq "") {
        continue;
    }
    Write-Host ""
    Write-Host "list 1 : $($list1.ItemCount) item $($item.Id) ------------------"
    foreach ($col in ($select -split ",")) {
        Write-Host "item $($item.Id) '$($col)' : '$($item[$col])'"
        "item 1 $($item.Id) '$($col)' : '$($item[$col])'" | Out-File -LiteralPath ".\log\myLog_1.txt" -Encoding utf8 -Append
    }

    #$found = $items2 | Where-Object {$_.FileLeafRef -eq $item["FileLeafRef"]} #) -and $_.FileDirRef -eq $item["FileDirRef"]
    $founds = @();
    
    $toFound = ToPdf -fileName $item["FileLeafRef"]
    foreach ($found in $items2) {
        if ("$($toFound)".Trim().ToLower() -eq "$($found["FileLeafRef"])".Trim().ToLower()) {
            $founds += $found 
        }
    }

    if ($null -eq $founds) {
        Write-Error "File Error : $($item["FileLeafRef"]))" -ForegroundColor Yellow
    }
    elseif ($founds.Count -eq 0) {
        Write-Host "File ne found $($($item["FileLeafRef"])) -> $($toFound)" -ForegroundColor Yellow
        "File ne found $($($item["FileLeafRef"])) -> $($toFound)" | Out-File -LiteralPath ".\log\myLog_NotFound.txt" -Encoding utf8 -Append
    }
    elseif ($founds.Count -gt 1) {
        Write-Error "More than 1 file"
    }
    elseif ($founds.Count -eq 1) {
        if ($item[$ColumnsToCompaire] -ne $founds[0][$ColumnsToCompaire]) {
            Write-Host "to update"
            "to update  $($item.Id) '$($toFound)' - origine : '$($item[$ColumnsToCompaire])' - pdf : '$($founds[0][$ColumnsToCompaire])'" | Out-File -LiteralPath ".\log\myLog_2.txt" -Encoding utf8 -Append
            Set-PnPListItem -UpdateType SystemUpdate -Identity $founds[0].Id  -Connection $con2 -List $list2 -Values @{$ColumnsToCompaire = $item[$ColumnsToCompaire] }
            Write-Host "updated"
        }
    }
}

Javascript Generate PDF

On 01/04/2025

<html>
<head>
<style>
.button {
  background-color: white;
  border: none;
  Border-radius:5px;
  color: black;
  padding: 15px 32px;
 border: 2px solid #008CBA; 
 text-align: center;
  font-weight : bold ;
  display: inline-block;
  font-size: 16px;
  margin: 4px 2px;
  cursor: pointer;
  top: 38%;
  right: 27%;
  position:absolute;
}
.button:hover {
  background-color: #008CBA;
  color: white;
}
.imagestyle{
    width: 50%;
    margin-left: 20%;
    position: absolute;
    top: -105px;
    display:none;

}
@media print {
@page {
      size:auto;
      margin:.5rem 0;
}
  #printPageButton {
    display: none;
  }
  #imagestyleId{
      display:block;
  }
 [data-automation-id^=QuickLinksWebPart]{
     display: none !important;
  }
  [data-automation-id=TitleTextId]{
     padding-top: 100px;
  }

  [data-automation-id=CanvasSection]{
     top: -140px;
  }
}
</style>
</head>
<body>
<script type="text/javascript">
function generatePdf() {
 const pageTitle = document.title;
 const printTitle = 'Mandate ' + pageTitle;
 document.title = printTitle;
 window.print();
 document.title = pageTitle;
 return false;
}
</script>

<input type="button" class="button" 
id="printPageButton"
value="Generate Mandate" onclick="generatePdf()">
<img src="tlstLogo.png" class="imagestyle" id="imagestyleId"/>

 

</body>
</html>

Sharepoint Rest Compaire 2 Lists Fields

On 25/03/2025


// Fonction pour comparer les champs de deux listes SharePoint
async function compareSharePointLists(urlSite1, urlSite2, ListRelativeUrl1, ListRelativeUrl2) {
    // Fonction auxiliaire pour obtenir les champs de la liste
    async function getListFields(urlSite, ListRelativeUrl) {
        const response = await fetch(`${urlSite}/_api/web/lists/getbytitle('${ListRelativeUrl}')/fields?$select=InternalName,TypeAsString`, {
            method: 'GET',
            headers: {
                'Accept': 'application/json;odata=verbose',
            },
        });

        if (!response.ok) {
            throw new Error(`Error fetching fields for list at ${ListRelativeUrl}: ${response.statusText}`);
        }

        const data = await response.json();
        return data.d.results;
    }

    try {
        // Obtenir les champs des deux listes
        const fields1 = await getListFields(urlSite1, ListRelativeUrl1);
        const fields2 = await getListFields(urlSite2, ListRelativeUrl2);

        // Comparer les champs
        fields1.forEach(field1 => {
            const matchingField = fields2.find(field2 => field2.InternalName === field1.InternalName);

            if (!matchingField) {
                console.log(`Le champ ${field1.InternalName} est manquant dans ${ListRelativeUrl2} de ${urlSite2}`);
            } else if (field1.TypeAsString !== matchingField.TypeAsString) {
                console.log(`Le type de champ ${field1.InternalName} ne correspond pas dans ${ListRelativeUrl2} de ${urlSite2} : ${field1.TypeAsString} vs ${matchingField.TypeAsString}`);
            }
        });

        fields2.forEach(field2 => {
            const matchingField = fields1.find(field1 => field1.InternalName === field2.InternalName);

            if (!matchingField) {
                console.log(`Le champ ${field2.InternalName} type ${field2.TypeAsString} est manquant dans ${ListRelativeUrl1} de ${urlSite1}`);
            }
        });
    } catch (error) {
        console.error('Erreur lors de la comparaison des champs des listes :', error);
    }
}

// Example usage
compareSharePointLists(
'https://test.sharepoint.com/sites/DoceboMigration', 
'https://test2.sharepoint.com/sites/fdiSandBox', 
'testConfiguration',
'fdiTasks');

Sharepoint List Groups And Permissions

On 24/03/2025


// Function to list all SharePoint groups of a site collection with their permission levels
async function listSharePointGroupsWithPermissions(siteUrl, targetDivId) {
    // Check if the siteUrl and targetDivId are provided
    if (!siteUrl || !targetDivId) {
        console.error("Site URL and target div ID must be provided.");
        // L'URL du site et l'ID de la div cible doivent être fournis.
        return;
    }

    // Construct the REST API URL to get the groups
    const groupsEndpoint = `${siteUrl}/_api/web/sitegroups`;

    try {
        // Fetch the groups from the SharePoint site
        const groupsResponse = await fetch(groupsEndpoint, {
            method: 'GET',
            headers: {
                'Accept': 'application/json;odata=verbose',
            },
        });

        // Check if the response is ok
        if (!groupsResponse.ok) {
            throw new Error(`Error fetching groups: ${groupsResponse.statusText}`);
            // Erreur lors de la récupération des groupes :
        }

        // Parse the JSON response
        const groupsData = await groupsResponse.json();
        const groups = groupsData.d.results;

        // Get the target div element
        const targetDiv = document.getElementById(targetDivId);
        if (!targetDiv) {
            throw new Error(`Target div with ID ${targetDivId} not found.`);
            // Div cible avec l'ID introuvable.
        }

        // Clear the target div
        targetDiv.innerHTML = '';
        
        const permsEndpoint = `${siteUrl}/_api/web/roleassignments?$expand=Member/users,RoleDefinitionBindings`;
        const permsResponse = await fetch(permsEndpoint, {
            method: 'GET',
            headers: {
                'Accept': 'application/json;odata=verbose',
            },
        })
        const permsData = await permsResponse.json();
            const roleAssignments = permsData.d.results;
        if (!permsResponse.ok) {
            throw new Error(`Error fetching roleassignments ${group.Title}: ${permsResponse.statusText}`);
            // Erreur lors de la récupération des utilisateurs pour le groupe
        }
        // Iterate through each group and display its information
        for (const group of groups) {
            // Fetch the role assignments for the group
            

            // Fetch the users in the group
            const usersEndpoint = `${siteUrl}/_api/web/sitegroups(${group.Id})/users`;
            const usersResponse = await fetch(usersEndpoint, {
                method: 'GET',
                headers: {
                    'Accept': 'application/json;odata=verbose',
                },
            });

            // Check if the response is ok
            if (!usersResponse.ok) {
                throw new Error(`Error fetching users for group ${group.Title}: ${usersResponse.statusText}`);
                // Erreur lors de la récupération des utilisateurs pour le groupe
            }

            // Parse the JSON response
            const usersData = await usersResponse.json();
            const users = usersData.d.results;

            // Create a div for the group
            const groupDiv = document.createElement('div');
            groupDiv.className = 'group';

            console.log(group.Title);
            // Create a header for the group
            const groupHeader = document.createElement('h3');
            groupHeader.textContent = `Group: ${group.Title}`;
            // Groupe :
            groupDiv.appendChild(groupHeader);

            // Create a list for the permission levels
            console.log("permissionsList", roleAssignments, group);
            const permissionsList = document.createElement('ul');
            roleAssignments.forEach(roleAssignment => {
                if(roleAssignment.PrincipalId == group.Id){
//Description Name
            roleAssignment.RoleDefinitionBindings.results.forEach(RoleDefinitionBinding => {
                    //RoleDefinitionBindings.results
                    const permissionItem = document.createElement('li');
                    permissionItem.textContent = `Permission Level: '${RoleDefinitionBinding.Name}' ${RoleDefinitionBinding.Description}`;
                    // Niveau de permission :
                    permissionsList.appendChild(permissionItem);
            });
                }
            });
            groupDiv.appendChild(permissionsList);

            // Create a list for the users in the group
            const usersList = document.createElement('ul');
            users.forEach(user => {
                const userItem = document.createElement('li');
                userItem.textContent = `User: ${user.Title}`;
                // Utilisateur :
                usersList.appendChild(userItem);
            });
            groupDiv.appendChild(usersList);

            // Append the group div to the target div
            targetDiv.appendChild(groupDiv);
        }
    } catch (error) {
        // Log the error to the console
        console.error(`Error: ${error.message}`);
        // Erreur :

        // Optionally, display the error message in the target div
        const targetDiv = document.getElementById(targetDivId);
        if (targetDiv) {
            targetDiv.innerHTML = `

Error: ${error.message}

`; //

Erreur : } } } // Example usage await listSharePointGroupsWithPermissions('https://test.sharepoint.com/sites/ssss', 'vpc_WebPart.unknown.a90bc6dc-fba2-4b5c-b7e2-f72005f01a14');