Résolu Utiliser une liste de valeurs dans un Foreach

Plus d'informations
il y a 3 ans 4 mois - il y a 3 ans 4 mois #30130 par Jonathan CHANAL
Bonjour à tous,

Je commence à créer des scripts sur PowerShell depuis quelques semaines. Je ne suis pas développeur... et je cherche un peu d'aide.

J'ai créé un script pour aller récupérer des fichiers en ligne. Tout est basé sur un fichier Excel que l'utilisateur doit compléter (pour rendre le système plus "User Friendly").

Mon problème c'est que je lorsque je souhaite récupérer les valeurs du fichier Excel, je les vois bien à l'écran en tapant par exemple $reportName ou $ListeRapportsTypeMeteor, mais impossible de les utiliser dans mon foreach (le système m'indique que la valeur est nulle...).

Voici mon code :
# get all the functions from the module and export as a spreadsheet
# Get-Command -Module ImportExcel | Select-Object Name | Export-Excel
# Get-Help -Name Import-Excel -Detailed
# Get-Help -Name Import-Excel -Examples

#Aller chercher l'état de la configuration
$Excel = New-Object -ComObject Excel.Application
$Excel.Visible = $false

# Chemin du fichier Excel de configuration --> à changer après phase de test par chemin suivant --> "C:\Scripts\0_Config_PowerBI.xlsx"
$FilePathExcel = "C:\Users\Jonathan\OneDrive - SYDEV\Mes Documents\Power BI\PowerShell\DevCamp 161020 - Ted Pattison\Exercices Réalisés\DevCamp\Scripts\0_Config_PowerBI.xlsx"

$Workbook = $Excel.Workbooks.Open($FilePathExcel)
$Worksheet = $Workbook.Worksheets.Item(1)
$State = $Worksheet.Cells.Item(1, 5).value2
$Ready2Go = "Configuration terminée"
$TypeRapport = $Worksheet.Cells.Item(10, 2).value2

if ($State -eq $Ready2Go) {

    Write-Host

    Connect-PowerBIServiceAccount | Out-Null

    if ( $TypeRapport -like "Meteor*" ) {
        # Récupération de la liste des rapports à télécharger Météor
        $TableauMeteor = Import-Excel -Path $FilePathExcel -StartRow "29" -StartColumn "1" -EndRow "39" -EndColumn "4" -HeaderName "Rapports à installer Météor", "Nom des rapports Météor", "A_Installer", "Nom des rapports Client"
        $RapportsMeteor = $TableauMeteor | Where-Object A_Installer -CContains "Oui"
        $ListeRapportsTypeMeteor = $RapportsMeteor."Nom des rapports Météor"
    }
    else {
        # Récupération de la liste des rapports à télécharger Mercure
        $TableauMercure = Import-Excel -Path $FilePathExcel -StartRow "14" -StartColumn "1" -EndRow "25" -EndColumn "4" -HeaderName "Rapports à installer Mercure", "Nom des rapports Mercure", "A_Installer", "Nom des rapports Client"
        $RapportsMercure = $TableauMercure | Where-Object A_Installer -CContains "Oui"
        $ListeRapportsTypeMercure = $RapportsMercure."Nom des rapports Mercure"
    }

    $sourceWorkspaceName = $TypeRapport

    if ( $sourceWorkspaceName -like "Meteor*" ) {
        $reportName = $ListeRapportsTypeMeteor
    }
    else {
        $reportName = $ListeRapportsTypeMercure
    }

    Write-Host "Votre import va comporter" $reportName.Count "rapport(s) provenant de l'espace de travail" $sourceWorkspaceName

    $sourceWorkspace = Get-PowerBIWorkspace -Name $sourceWorkspaceName

    foreach ($element in $reportName) {
        $report = Get-PowerBIReport -WorkspaceId $sourceWorkspace.Id -Name $element
        $reportId = $report.Id
    
        Write-Host "Exportation du rapport depuis l'espace modèle vers votre dossier Rapports A installer..."
        New-Item -ItemType Directory -Force -Path "$PSScriptRoot/Rapports à Installer" | Out-Null
        $reportTempFilePath = "$PSScriptRoot/Rapports à Installer/$element.pbix"
        Export-PowerBIReport -WorkspaceId $sourceWorkspace.Id -Id $reportId -OutFile $reportTempFilePath 
    }

    if ($reportName.Count -gt 1) {
        write-host "Vos rapports ont bien été téléchargés, vous pouvez les modifier et poursuivre la procédure"    
    }
    else {
        write-host "Votre rapport a bien été téléchargé, vous pouvez le modifier et poursuivre la procédure"
    }

}

else {
    write-host "Commencez d'abord par compléter le fichier Excel de configuration." 
}

#Fermer Excel proprement
Start-Sleep 5
$Excel.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($Excel)
Remove-Variable Excel

Le problème c'est -Name $element dans le foreach qui ne fonctionne pas. Cet element fait référence à $reportName qui affiche bien la liste de mes rapports... Je pense donc que le problème vient dans la façon d'y faire référence plus haut : $ListeRapportsTypeMeteor = $RapportsMeteor."Nom des rapports Météor" --> j'aimerais que cette ligne crée un tableau, j'avais écris $ListeRapportsTypeMeteor = @($RapportsMeteor."Nom des rapports Météor") mais ça ne marchait pas mieux...

J'en profite pour une seconde question au passage : je souhaite que ce script pointe toujours vers le répertoire d'installation du script. J'ai utilisé $PSScriptRoot à cet effet mais cela ne fonctionne pas... J'ai dû remplacer par le chemin actuel de mon fichier (très long) et cela m'obligera plus tard à demander à l'utilisateur d'installer le répertoire à la racine de C par exemple, ce que je ne souhaite pas... Une idée ou une piste de recherche serait la bienvenue. Ok j'ai trouvé, ça fonctionne uniquement à l'exécution du script et pas quand je ne sélectionne qu'une partie du code.

Un exemple en pièce jointe des valeurs que j'obtiens au fur et à mesure de l'avancement du script. Elles sont donc bien là mais pas dans le foreach...

Merci d'avance pour votre aide.

Jonathan
Pièces jointes :
Dernière édition: il y a 3 ans 4 mois par Jonathan CHANAL.

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 3 ans 4 mois #30132 par Arnaud Petitjean
Bonjour Jonathan,

Si ton ForEach ne fonctionne pas correctement, c'est à mon avis parce que ta variable $reportName n'est pas un tableau.

Pour en avoir le coeur net, pourrais tu nous donner le résultat des commandes suivantes:
$reportName | Get-Member
$reportName.gettype()

Arnaud

MVP PowerShell et créateur de ce magnifique forum :-)
Auteur de 6 livres PowerShell aux éditions ENI
Fondateur de la société Start-Scripting
Besoin d'une formation PowerShell ?

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 3 ans 4 mois #30133 par Jonathan CHANAL
Bonjour Arnaud,

Merci beaucoup pour ton aide. Voici le résultat de la commande :
PS C:\Users\Jonathan> $ReportName | Get-Member
    $reportName.GetType()


   TypeName: System.String

Name                 MemberType            Definition
----                 ----------            ----------
Clone                Method                System.Object Clone(), System.Object ICloneable.Clone()
CompareTo            Method                int CompareTo(System.Object value), int CompareTo(string strB), int IComparable.CompareTo(System.Object obj), int IComparable[string].CompareTo(string other)
Contains             Method                bool Contains(string value), bool Contains(string value, System.StringComparison comparisonType), bool Contains(char value), bool Contains(char value, System.StringComparison comparisonType)
CopyTo               Method                void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count)
EndsWith             Method                bool EndsWith(string value), bool EndsWith(string value, System.StringComparison comparisonType), bool EndsWith(string value, bool ignoreCase, cultureinfo culture), bool EndsWith(char value)
EnumerateRunes       Method                System.Text.StringRuneEnumerator EnumerateRunes()
Equals               Method                bool Equals(System.Object obj), bool Equals(string value), bool Equals(string value, System.StringComparison comparisonType), bool IEquatable[string].Equals(string other)
GetEnumerator        Method                System.CharEnumerator GetEnumerator(), System.Collections.IEnumerator IEnumerable.GetEnumerator(), System.Collections.Generic.IEnumerator[char] IEnumerable[char].GetEnumerator()
GetHashCode          Method                int GetHashCode(), int GetHashCode(System.StringComparison comparisonType)
GetPinnableReference Method                System.Char&, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e GetPinnableReference()
GetType              Method                type GetType()
GetTypeCode          Method                System.TypeCode GetTypeCode(), System.TypeCode IConvertible.GetTypeCode()
IndexOf              Method                int IndexOf(char value), int IndexOf(char value, int startIndex), int IndexOf(char value, System.StringComparison comparisonType), int IndexOf(char value, int startIndex, int count), int IndexOf(string value), int IndexOf(string value, int startIndex), int IndexOf(… 
IndexOfAny           Method                int IndexOfAny(char[] anyOf), int IndexOfAny(char[] anyOf, int startIndex), int IndexOfAny(char[] anyOf, int startIndex, int count)
Insert               Method                string Insert(int startIndex, string value)
IsNormalized         Method                bool IsNormalized(), bool IsNormalized(System.Text.NormalizationForm normalizationForm)
LastIndexOf          Method                int LastIndexOf(char value), int LastIndexOf(char value, int startIndex), int LastIndexOf(char value, int startIndex, int count), int LastIndexOf(string value), int LastIndexOf(string value, int startIndex), int LastIndexOf(string value, int startIndex, int count),… 
LastIndexOfAny       Method                int LastIndexOfAny(char[] anyOf), int LastIndexOfAny(char[] anyOf, int startIndex), int LastIndexOfAny(char[] anyOf, int startIndex, int count)
Normalize            Method                string Normalize(), string Normalize(System.Text.NormalizationForm normalizationForm)
PadLeft              Method                string PadLeft(int totalWidth), string PadLeft(int totalWidth, char paddingChar)
PadRight             Method                string PadRight(int totalWidth), string PadRight(int totalWidth, char paddingChar)
Remove               Method                string Remove(int startIndex, int count), string Remove(int startIndex)
Replace              Method                string Replace(string oldValue, string newValue), string Replace(string oldValue, string newValue, bool ignoreCase, cultureinfo culture), string Replace(string oldValue, string newValue, System.StringComparison comparisonType), string Replace(char oldChar, char new… 
Split                Method                string[] Split(char separator, System.StringSplitOptions options), string[] Split(char separator, int count, System.StringSplitOptions options), string[] Split(Params char[] separator), string[] Split(char[] separator, int count), string[] Split(char[] separator, S… 
StartsWith           Method                bool StartsWith(string value), bool StartsWith(string value, System.StringComparison comparisonType), bool StartsWith(string value, bool ignoreCase, cultureinfo culture), bool StartsWith(char value)
Substring            Method                string Substring(int startIndex), string Substring(int startIndex, int length)
ToBoolean            Method                bool IConvertible.ToBoolean(System.IFormatProvider provider)
ToByte               Method                byte IConvertible.ToByte(System.IFormatProvider provider)
ToChar               Method                char IConvertible.ToChar(System.IFormatProvider provider)
ToCharArray          Method                char[] ToCharArray(), char[] ToCharArray(int startIndex, int length)
ToDateTime           Method                datetime IConvertible.ToDateTime(System.IFormatProvider provider)
ToDecimal            Method                decimal IConvertible.ToDecimal(System.IFormatProvider provider)
ToDouble             Method                double IConvertible.ToDouble(System.IFormatProvider provider)
ToInt16              Method                short IConvertible.ToInt16(System.IFormatProvider provider)
ToInt32              Method                int IConvertible.ToInt32(System.IFormatProvider provider)
ToInt64              Method                long IConvertible.ToInt64(System.IFormatProvider provider)
ToLower              Method                string ToLower(), string ToLower(cultureinfo culture)
ToLowerInvariant     Method                string ToLowerInvariant()
ToSByte              Method                sbyte IConvertible.ToSByte(System.IFormatProvider provider)
ToSingle             Method                float IConvertible.ToSingle(System.IFormatProvider provider)
ToString             Method                string ToString(), string ToString(System.IFormatProvider provider), string IConvertible.ToString(System.IFormatProvider provider)
ToType               Method                System.Object IConvertible.ToType(type conversionType, System.IFormatProvider provider)
ToUInt16             Method                ushort IConvertible.ToUInt16(System.IFormatProvider provider)
ToUInt32             Method                uint IConvertible.ToUInt32(System.IFormatProvider provider)
ToUInt64             Method                ulong IConvertible.ToUInt64(System.IFormatProvider provider)
ToUpper              Method                string ToUpper(), string ToUpper(cultureinfo culture)
ToUpperInvariant     Method                string ToUpperInvariant()
Trim                 Method                string Trim(), string Trim(char trimChar), string Trim(Params char[] trimChars)
TrimEnd              Method                string TrimEnd(), string TrimEnd(char trimChar), string TrimEnd(Params char[] trimChars)
TrimStart            Method                string TrimStart(), string TrimStart(char trimChar), string TrimStart(Params char[] trimChars)
Chars                ParameterizedProperty char Chars(int index) {get;}
Length               Property              int Length {get;}

IsCollectible              : False
DeclaringMethod            :
FullName                   : System.Object[]
AssemblyQualifiedName      : System.Object[], System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
Namespace                  : System
GUID                       : 00000000-0000-0000-0000-000000000000
GenericParameterAttributes :
IsSZArray                  : True
GenericParameterPosition   :
ContainsGenericParameters  : False
StructLayoutAttribute      :
Name                       : Object[]
DeclaringType              :
Assembly                   : System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
BaseType                   : System.Array
IsByRefLike                : False
IsConstructedGenericType   : False
IsGenericType              : False
IsGenericTypeDefinition    : False
IsGenericParameter         : False
IsTypeDefinition           : False
IsSecurityCritical         : True
IsSecuritySafeCritical     : False
IsSecurityTransparent      : False
MemberType                 : TypeInfo
MetadataToken              : 33554432
Module                     : System.Private.CoreLib.dll
ReflectedType              :
TypeHandle                 : System.RuntimeTypeHandle
UnderlyingSystemType       : System.Object[]
GenericTypeParameters      : {}
DeclaredConstructors       : {Void .ctor(Int32)}
DeclaredEvents             : {}
DeclaredFields             : {}
DeclaredMembers            : {System.Object Get(Int32), Void Set(Int32, System.Object), System.Object& Address(Int32), Void .ctor(Int32)}
DeclaredMethods            : {System.Object Get(Int32), Void Set(Int32, System.Object), System.Object& Address(Int32)}
DeclaredNestedTypes        : {}
DeclaredProperties         : {}
ImplementedInterfaces      : {System.ICloneable, System.Collections.IList, System.Collections.ICollection, System.Collections.IEnumerable…}
IsInterface                : False
IsNested                   : False
IsArray                    : True
IsByRef                    : False
IsPointer                  : False
IsGenericTypeParameter     : False
IsGenericMethodParameter   : False
IsVariableBoundArray       : False
HasElementType             : True
GenericTypeArguments       : {}
Attributes                 : AutoLayout, AnsiClass, Class, Public, Sealed, Serializable
IsAbstract                 : False
IsImport                   : False
IsSealed                   : True
IsSpecialName              : False
IsClass                    : True
IsNestedAssembly           : False
IsNestedFamANDAssem        : False
IsNestedFamily             : False
IsNestedFamORAssem         : False
IsNestedPrivate            : False
IsNestedPublic             : False
IsNotPublic                : False
IsPublic                   : True
IsAutoLayout               : True
IsExplicitLayout           : False
IsLayoutSequential         : False
IsAnsiClass                : True
IsAutoClass                : False
IsUnicodeClass             : False
IsCOMObject                : False
IsContextful               : False
IsEnum                     : False
IsMarshalByRef             : False
IsPrimitive                : False
IsValueType                : False
IsSignatureType            : False
TypeInitializer            :
IsSerializable             : True
IsVisible                  : True
CustomAttributes           : {[System.SerializableAttribute()]}


PS C:\Users\Jonathan>

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 3 ans 4 mois #30134 par Arnaud Petitjean
C'est curieux car on voit qu'il s'agit bien d'un tableau de String.

Pour le vérifier :
$ReportName[0]

Le problème doit se situer à l'intérieur de ton foreach...

Une petite astuce que j'utilise souvent c'est de faire une exécution pas-à-pas en mode interactif.
Essaie de placer l'instruction suivante à l'intérieur de ton bloc foreach :
$host.EnterNestedPrompt()

Au moment de l'exécution tu verras que ton prompt affiche un double chevron ">>". Cela indique que tu es dans un shell imbriqué. Tu pourras ainsi observer (voire modifier) les variables et comprendre ce qui dysfonctionne.
Quand tu auras terminé, tu tapes la command Exit et l'exécution se poursuivra normalement.

Arnaud

MVP PowerShell et créateur de ce magnifique forum :-)
Auteur de 6 livres PowerShell aux éditions ENI
Fondateur de la société Start-Scripting
Besoin d'une formation PowerShell ?

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 3 ans 4 mois #30135 par Jonathan CHANAL
Merci beaucoup. Je n'arrive pas à exécuter le code pas à pas, j'ai des chevrons mais sans rien à côté... Je vais aller voir comment fonctionne ce système, il doit y avoir un tuto là-dessus quelque part.

J'ai modifié mon code pour essayer de le simplifier (mais c'est toujours le même problème au même endroit...) :
#Aller chercher l'état de la configuration
$Excel = New-Object -ComObject Excel.Application
$Excel.Visible = $false

# Chemin du fichier Excel de configuration --> à changer après phase de test par chemin suivant --> "C:\Scripts\0_Config_PowerBI.xlsx"
$FilePathExcel = "$PSScriptRoot\0_Config_PowerBI.xlsx"

$Workbook = $Excel.Workbooks.Open($FilePathExcel)
$Worksheet = $Workbook.Worksheets.Item(1)
$State = $Worksheet.Cells.Item(1, 5).value2
$Ready2Go = "Configuration terminée"
$sourceWorkspaceName = $Worksheet.Cells.Item(10, 2).value2

if ($State -eq $Ready2Go) {

    Write-Host

    Connect-PowerBIServiceAccount | Out-Null

    if ( $sourceWorkspaceName -like "Meteor*" ) {
        # Récupération de la liste des rapports à télécharger Météor
        $TableauData = Import-Excel -Path $FilePathExcel -StartRow "29" -StartColumn "1" -EndRow "39" -EndColumn "4" -HeaderName "Rapports à installer Météor", "Nom des rapports", "A_Installer", "Nom des rapports Client"
    }
    else {
        # Récupération de la liste des rapports à télécharger Mercure
        $TableauData = Import-Excel -Path $FilePathExcel -StartRow "14" -StartColumn "1" -EndRow "25" -EndColumn "4" -HeaderName "Rapports à installer Mercure", "Nom des rapports", "A_Installer", "Nom des rapports Client"
    }

    $RapportsTypes = $TableauData | Where-Object A_Installer -CContains "Oui"
    $reportName = $RapportsTypes."Nom des rapports"
        
    Write-Host "Votre import va comporter" $RapportsTypes.Count "rapport(s) provenant de l'espace de travail" $sourceWorkspaceName

    foreach ($element in $reportName) {
        $sourceWorkspace = Get-PowerBIWorkspace -Name $sourceWorkspaceName
        $report = Get-PowerBIReport -WorkspaceId $sourceWorkspace.Id -Name $element
        
        Write-Host "Exportation du rapport $element depuis l'espace modèle vers votre dossier Rapports A installer..."
                
        New-Item -ItemType Directory -Force -Path "$PSScriptRoot/Rapports à Installer" | Out-Null
        $reportTempFilePath = "$PSScriptRoot/Rapports à Installer/$element.pbix"
        Export-PowerBIReport -WorkspaceId $sourceWorkspace.Id -Id $report.Id -OutFile $reportTempFilePath 
    }

    if ($reportName.Count -gt 1) {
        write-host "Vos rapports ont bien été téléchargés, vous pouvez les modifier et poursuivre la procédure"    
    }
    else {
        write-host "Votre rapport a bien été téléchargé, vous pouvez le modifier et poursuivre la procédure"
    }

}

else {
    write-host "Commencez d'abord par compléter le fichier Excel de configuration." 
}

#Fermer Excel proprement
Start-Sleep 5
$Excel.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($Excel)
Remove-Variable Excel

Je vais creuser encore...

A plus tard, bon week-end

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 3 ans 4 mois #30136 par Arnaud Petitjean

Je n'arrive pas à exécuter le code pas à pas, j'ai des chevrons mais sans rien à côté...


C'est normal, c'est le fonctionnement attendu ;-)

Une fois dans ce mode, tu peux observer le contenu de toutes tes variables, voire même les modifier.
Ainsi tu peux éventuellement mieux comprendre d'où vient ton problème.

Pour accéder à tes variables, c'est comme dans PowerShell. Tu tapes le nom de la variable et le contenu s'affichera.

Arnaud

MVP PowerShell et créateur de ce magnifique forum :-)
Auteur de 6 livres PowerShell aux éditions ENI
Fondateur de la société Start-Scripting
Besoin d'une formation PowerShell ?

Connexion ou Créer un compte pour participer à la conversation.

Temps de génération de la page : 0.077 secondes
Propulsé par Kunena