Un model de automatizare raportare in Excel

Zilele acestea sunt foarte aglomerate pe la serviciu. O mulțime de cerințe și problemuțe care trebuie rezolvate cât mai pe loc posibil. Dar între zeci de emailuri a apărut unul care mi-a atras atenția.

Păi putem să refuzăm noi un ajutor în legătură cu Excelul? Păi nu. Așa că lăsăm totul deoparte și ne apucăm de treabă.

Descriere problemei

Se dorește ca în fiecare dimineață, datele agregate dintr-un fișier Excel să fie trimise prin email la o anumită oră către o anumită adresă de distribuție. Soluțiile existente pe internet sunt în mare parte cu VBA și o serie de operațiuni manuale, care implică deschiderea fișierelor. La altele nu m-am uitat, dar cred că se pot face și cu ceva automatizări din Power Automate. Dar cum nu toată lumea are subscripție de cloud, m-am gândit la Task Scheduler-ul de Windows. Și cum nu sunt nici fan VBA nici prea multe despre programare nu știu, m-am decis să abordez problema din PowerShell pe care-l știu de pe vremea când eram administrator de rețea și actualmente îl folosesc în administrarea de SharePoint.

Propunerea de soluție

Propun un exemplu de fișier Excel care conține o funcție de generare aleatorie de numere:

Funcția =RANDBETWEEN(1;49) generează numere aleatorii în cazul meu între 1 și 49 iar în C3 fac suma lor. Orice celulă se modifică se schimbă și numerele și suma lor.

Scriptul de refresh silent a fișierului.

Acest script presupune că aveți deja instalat pachetul Microsoft Excel pe calculator. Cu acest script se deschide fișierul din calea specificată în secțiunea 2. După care accesează prima foaie de calcul (3) și execută refresh la date (4), salvează (5), închide fișierul (6) și Excelul (7) după care eliberează memoria de obiecte (8).

# Actualizare silent date fisier Excel
# Author: Valy Greavu 
# Date: 13.02.2024
# Se recomandă utilizarea în Task Scheduler pentru refresh fișiere din când în când la noile date.

# 1. Se crează o instanță Excel
$excel = New-Object -ComObject Excel.Application

# 2. Se deschide fișierul Excel. Atentie la calea fisierului.
$workbook = $excel.Workbooks.Open("P:\Temp\FisierExcel.xlsx")

# 3. Se activează prima foaie de lucru din Excel în care sunt datele care se actualizează. 
# Item(2) inseamna a doua foaie de lucru in ordine.
$worksheet = $workbook.Sheets.Item(1)
$worksheet.Activate()

# 4. Se realizează refresh la date din diferite surse sau se recalculează formulele și funcțiile
$workbook.RefreshAll()

# 5. Se salvează modificările
$workbook.Save()

# 6. Se închide fișierul Excel
$workbook.Close()

# 7. Se închide aplicația Excel creată la pasul 1.
$excel.Quit()

# 8. Se eliberează obiectele COM
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($worksheet) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($workbook) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel) | Out-Null
Remove-Variable excel, workbook, worksheet

La fiecare rulare datele din Excel se reîmprospătează. O condiție importantă este ca acel fișier Excel să fie închis.

Scriptul de trimitere a datelor din Excel prin email

În acest script se preiau datele din fișierul Excel specificat la secțiunea 3. Înainte de preluare date ar trebui verificat dacă există sau nu instalat modulul ImportExcel în PowerShell. Dacă nu este se instalează cu linia comentată din secțiunea 1.

În acest script preiau valorile din celulele A2 și C3 (prima generată aleatoriu și suma tuturor valorilor). Specificul versiunii curente a modului Import-Excel este că trebuie să specificăm coloanele și liniile de start și de final în formatul R1C1.

În modelul meu numele foii de calcule este Sheet1.

# Preluare date din Excel și trimitere email
# Author: Valy Greavu 
# Date: 13.02.2024
# Se recomandă rulare script Refresh fisier Excel silent.ps1 înainte de trimitere email pentru actualizare date.
# Se recomandă utilizarea în Task Scheduler pentru trimitere email la o anumită dată.


# 1. Se instalează modulul Import-Excel dacă nu este deja instalat. 
# Operatiunea se realizeaza o singura data pe un calculator.
# În acest script linia de install este comentată

# Install-Module -Name ImportExcel -Scope CurrentUser -Force

# 2. Se importă modulul Import-Excel
Import-Module ImportExcel

# 3. Se specifică calea către fișierul Excel din care dorim preluarea datelor
$filePath = "P:\Temp\FisierExcel.xlsx"

# 4. Extrage valorile din anumite celule din foaia de calcul Sheet1 în acest exemplu celulele A2 și C3.
# Se pot extrage și blocuri de valori

$cellValue1 = (Import-Excel -Path $filePath -StartColumn 1 -StartRow 2 -NoHeader -EndRow 2 -EndColumn 1 -WorksheetName Sheet1).P1 # Celula A2
$cellValue2 = (Import-Excel -Path $filePath -StartColumn 3 -StartRow 3 -NoHeader -EndRow 3 -EndColumn 3 -WorksheetName Sheet1).P1 # Celula C3


# 5. Se construiește mesajul de email
# În acest exemplu trimit un email din Office 365 către Outlook.com

$subject = "Valori din Excel"
$body = "Buna ziua,`n`nValoarea din A2: $cellValue1`nSuma numerelor din C3: $cellValue2`n`nO zi buna!"
$to = "valy.greavu@outlook.com"
$emailAddress = "valy.greavu@feaa.uaic.ro"


# 6. Se specifică datele serverului SMTP al Outlook.com și portul
# Trebuie văzut la fiecare serviciu care sunt specificațiile de SMTP
# Trebuie văzut dacă serviciul utilizat suportă modern authentication (two factor authentication) pentru a compune credențialele de acces

$smtpServer = "smtp.office365.com"
$smtpPort = 587


# 7. În cazul în care nu automatizăm prin Task Scheduler putem folosi Prompt pentru parolă
$securePassword = Read-Host -Prompt "Introdu parola" -AsSecureString

# 7.1. Operatiune nerecomandata pentru ca salveaza parola in script in cazul in care dorim sa utilizam cu Task Scheduled dintr-un mediu securizat
# $password = "*************" # se trece parola în clear sau
# $credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $emailAddress, (ConvertTo-SecureString -String $password -AsPlainText -Force)

# 7.2. Crearea obiectului de tip credențiale de autentificare pentru serviciul de email specificat.
# O altă verrsiune non-auto este să folosim comanda Get-Credential
$credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $emailAddress, $securePassword


# 8. Trimiterea emailului. 
# În cazul în care avem mai multe adrese la care trebuie să trimitem putem să le importăm dintr-un CSV și să folosim foreach
Send-MailMessage -To $to -From $emailAddress -Subject $subject -Body $body -SmtpServer $smtpServer -Port $smtpPort -UseSsl -Credential $credential

# Final script

Problemele mai mari care pot apărea sunt legate de serviciul de email utilizat pentru trimiterea datelor și tipul de autentificare suportat de SMTP. În exemplul meu folosesc un cont de Office 365 pentru a trimite datele. Sunt mai multe metode de a obține acel $credential corect, în funcție de furnizorul de email. Unele sisteme suportă inclusiv two factor authetication.

Personal nu recomand secțiunea 7.1. de salvare a parolei direct în script, dar este o opțiune pentru automatizare mai ales prin Task Scheduler.

Definirea task-urilor în Task scheduler

La final pentru automatizare se creează două task-uri noi în Excel cu programare dorită în cazul meu zilnic.

Și acțiunea de rulare a PowerShell și calea către fișier.

Cam asta ar fi. Sper să fie util cuiva.

Campionatul Mondial de #Excel #FMWC – 2023

Acest articol este o scurtă descriere a experienței mele la Campionatul mondial de Excel, ediția 2023.

Informația pe scurt: A fost super, chiar dacă nu am reușit să mă calific pe tabloul principal de 128. Poate anul viitor.

În urmă cu mai bine de 1 an, undeva prin august, un prieten m-am provocat să mă înscriu și eu în această competiție, organizată de FMWC – Financial Modeling World Cup https://www.fmworldcup.com/, o asociere de companii din domeniul financiar, software și consultanță, care au reușit să creeze un concept foarte interesant de eSports din rezolvarea unor probleme prin utilizarea Microsoft Excel.

Am participat la calificările din 2022 dar a fost foarte bizar pentru că lipsit de experiență, nici nu știam unde să dau răspunsurile.

Ediția 2023 în schimb a fost mult mai interesantă pentru că s-a transformat într-o competiție pe o perioadă mai lungă de timp. În fiecare lună s-a organizat câte o rundă de calificare, din care erau aleși doar primii 5. În fiecare rundă era prezentat un caz diferit.

Formatul unei runde

Pentru a putea participa, ca la orice competiție sportivă trebuie să te înscrii prin plata taxei de participare. Prețul este de 20$ fără TVA.

Competițiile sunt anunțate pentru fiecare lună dinainte și pot fi la 5PM GMT sau 7 AM GMT.

Înainte cu câteva minute de ora de start, se primește un email în există un link către un site web de unde se descarcă fișierul de lucru și în care trebuie să dai răspunsurile în timp ce rezolvi.

Fiecare fișier de lucru are 5 niveluri de dificultate, de la Very Easy sau Easy pana la Hard sau Very Hard. Pe lângă cele 5 niveluri cu scor diferit fiecare mai există de obicei 3 întrebări bonus. În final poți obține maximum 1250 de puncte.

Pe măsură ce rezolvi un nivel completezi întrebările din pagina web deschisă.

Fiecare rundă durează 30 de minute.

La finalul rundei trebuie salvat modelul pe care ai lucrat și încărcat în pagina de examen. Fără acel fișier, rezultatele din pagină nu sunt luate în calcul.

După finalizarea celor 30 de minute se intră în live-uri, în care sunt invitați de obicei 4 jucători (din top 20-50) pentru a rezolva live cazul. Există de asemenea moderatori care comentează live evenimentul pentru urmăritorii de pe Youtube.

Rezultatele se publică la câteva ore de la finalizarea rundei pe https://www.fmworldcup.com/excel-esports/road-to-las-vegas-2023-rankings/

În medie la fiecare din cele 9 runde au participat cam 120 de jucători, eu reușind să obțin punctaj de fiecare dată. Ce e drept puțin, dar a fost. Runda 5 a fost cea în care am obținut cel mai bun punctaj de peste 500.

Precalificările

În Weekend au fost organizate sesiunile de precalificări pentru tabloul principal… unde au participat peste 500 de oameni din întreaga lume. În 2022 au participat 526 de oameni din întreaga lume.

Din cei 500, aproape 150 nu au reușit să trimită fișierul cu rezolvările… eu reușind în ultima secundă din ultimul minut să încarc fișierul.

Rezultatele centralizate aici: https://www.fmworldcup.com/excel-esports/mewc-2023-rankings/

Personal nu sunt mulțumit de rezultatul obținut, dar sunt super încântat de cât de mult am reușit să învăț. Un pic mai mult antrenament și aș fi putut obține un scor și mai bun.

La una din probleme am reușit să o rezolv dintr-o singură funcție, exact în stilul celor pe care-i urmăresc pe diferite canale. În funcție parsez textul pas cu pas și-l transfer între tabele intermediare totul într-o sigură formulă.

Una din probleme este că nici nu lucrez Excel zi de zi, iar ceea ce se face la facultate… este la nivel începător. Un alt aspect este dat de faptul că nu mi-am permis financiar să-mi cumpăr un pachet de instruire / antrenament… care poate ajunge la câteva sute de dolari.

Una peste alta, deja m-am înscris pentru ediția 2024!

Pentru cei care doresc să vadă live-ul din calificări: https://www.youtube.com/@FMWC

O descriere mai pe larg despre experiența mea în competiție, găsiți meet-up-ul organizat de Romania Power BI & Modern Excel User Group. Înregistrarea evenimentului aici: https://www.youtube.com/watch?v=aDjghQvt_f4&t=2925s&ab_channel=SSBICentral

E clar când nu ești sub presiunea timpului ai timp și de artificii.

Mi-ar plăcea să văd cât mai mulți români în competiție și să ne „antrenăm” împreună! De asemenea, este și competiție pentru studenți… dar cu un pic mai multă orientare spre zona de financiar.

Mie mi-a plăcut și mai ales mă bucur că o astfel de competiție te scoate din zona de confort și te pune serios pe învățat.

Braille translator in Excel

Îmi ești dragă ca lumina ochilor mei!

Probabil una din cele mai de presus expresii ale iubirii, rostite de multe ori fără semnificația profundă pentru mulți dintre noi.

La ora actuală se estimează că la nivel mondial sunt peste 36 de milioane de persoane nevăzătoare, din care aproximativ 100.000 în România. Sunt convins că există pe lumea asta multe aplicații software care-i ajută pe mulți să învețe să scrie și să citească în limbajul Braille. Vedem și noi astfel de simboluri prin din ce în ce mai multe locuri civilizate și nu le înțelegem semnificația.

Acest articol este o propunere de utilizare cu scopul de a genera text tipăribil în format Braille (vezi imagine 1). Există mai multe site-uri pentru a genera text Braille sau dispozitive electronice (foarte scumpe) de a scrie și citi Braille.

În cazul în care cineva de la o organizație a nevăzătorilor dispune de o astfel de imprimantă vă rog să testați și să mă contactați dacă este nevoie de îmbunătățiri asupra aplicației.

Fișierul poate fi deschis de la adresa: https://1drv.ms/x/s!ApGubfWFh8NurOhXSganso3njoqMmg?e=ZVGZ3o

Pentru a putea vedea cardurile generate ar fi indicat să activați partea de Turn on images.

În fișierul Excel am folosit noua funcție IMAGE() care permite aducerea unei imagini de pe internet într-o celulă și a efectua operațiuni cu ea.

În fișier, textul poate fi editat doar în zonele dedicate. Fișierul este creat în versiunea Excel din Microsoft 365 deci nu poate fi utilizat pe calculatoarele personale dacă nu dispuneți de o astfel de licență.

Fișierul este în editare publică, pentru a permite tuturor testarea. Orice utilizare în alte scopuri decât cele dedicate excedă responsabilitatea autorului.

UPDATE 17.08.2023

Mulțumesc tuturor celor care au distribuit acest articol. Am avut deosebita plăcere de a discuta cu oameni foarte faini legat de utilitatea acestui exercițiu și despre experiența lor cu lumea IT. În sinteză oamenii sunt bine, dar dacă fiecare dintre noi s-ar putea implica mai mult, ar fi și mai bine.

Cel mai mult m-a ajutat la validare și completare cu caractere românești domnul Aurel Pătru, profesor nevăzător la Liceul special Sfânta Maria din Arad.

Braille pentru ei este important pentru a putea citi în diferite locuri, dar cel mai mult îi ajută funcțiile de accesibilitate din sistemele de operare. Ei folosesc aceste funcții atât pe calculatoare/laptop-uri cât și pe telefoanele mobile. Au o nevoie de comunicare la fel ca toți ceilați și personal mă bucur că suntem împreună pe Internet sau alte canale de comunicare.

Astăzi am avut plăcerea să discut și cu dl Dan Patzelt de la http://www.tactileimages.org/ și mi-a povestit mult despre cum încearcă ei să ajute nevăzătorii și provocările tehnice și financiare pe care trebuie să le depășească.

Dincolo de exercițiul meu, care și-a atins scopul, utilitatea Excelului creat… nu este la fel de mare pe cât o credeam la început, pentru că ei scriu textul în clasic iar echipamentele de imprimare fac translatarea în alfabet Braille automat. :) (de asta probabil sunt și atât de scumpe).

Am actualizat fișierul Excel cu diactitice, cu specificarea faptului că sunt probleme la interpretarea literelor mari pentru diacritice. Acestea au același cod ASCII în Excel atât pentru litere mari cât și pentru cele mici… De asemenea, am modificat puți partea de printare în carduri pentru a răspunde cerinței de a avea maxim 32 x 18 carduri (cum le spun eu) pe o pagină A4.

END UPDATE

Povestea mai pe larg

Mă antrenez pentru Campionatul mondial de Excel eSports: https://www.fmworldcup.com/excel-esports/ Chiar vreau să ajung în primii 50 din lume, deci trebuie să trag tare.

Una din teme este manipularea caracterelor și codurilor prin funcțiile CHAR(), CODE(), UNICODE() și UNICHAR(). De asemenea sunt foarte importante funcțiile de parsare text și tabele, coloane, rânduri și reunificarea lor.

Studiind codurile unicode am descoperit și codurile pentru caracterele Braille. Fiecare simbol Braille reprezintă un set de puncte aranjate într-o matrice de 2×3. Aceasta oferă o structură uniformă pentru litere și cifre. Cu toate că majoritatea literelor majuscule sunt reprezentate printr-un singur simbol Braille, cifrele sunt reprezentate prin două simboluri alăturate. Acest lucru ajută la distingerea clară între cifre și litere într-un text Braille, reducând astfel confuzia și greșelile de interpretare.

Mai auzisem despre limbaj, dar acum aveam un motiv să abordez problema translatării cu adevărat. În foaia de calcul Sursa se află un tabel care conține ceea ce am găsit pe Braille ASCII – Wikipedia. Sunt mai multe simboluri dar am scos dintre ele caracterele speciale din Germană. De asemenea, în tabelul de pe Wikipedia sunt ceva probleme de reprezentare. Tot în sursa am introdus caracter cu caracter sursa imaginilor pentru carduri. Acestea sunt foarte importante pentru printare. Dacă folosești doar punctuația nu cred că este suficient pentru o imprimantă de acest gen. Pe coloana Dots se află punctuația în format 01 în care fiecare 1 reprezintă un punct de pe matricea de 2×3.

Propunerea mea de limbaj este una destul de simplă și am încercat să mă validez cu site-ul școlii: http://www.spdv.ro/braille/ care mi s-a părut a fi unul din cele mai stabile și sigure. Am folosit și site-uri pentru Engleză: https://wecapable.com/braille-translator/english-to-braille-converter/

Trebuie menționat că în sursă nu am diacriticele din limba română pentru că nu am găsit codurile Unicode pentru ele, neexistând o corespondență între vizual (setul de puncte – Dots) și unicode-ul zecimal de pe coloana DecUni.

Propunerea este simplă și prin faptul că nu este adaptată complexității metodelor de scriere din Engleză. M-am documentat pe site-ul https://en.wikipedia.org/wiki/English_Braille ca să înâeleg până unde se poate ajunge, dar mai este mult de lucru pentru acel format de scriere. Menționez că am interacționat cu „AI-urile” pentru a încerca să înțeleg mai repede și mai bine modul de scriere, dar dacă Bard este un pic mai răsărit ca iON () tot cu ChatGPT am ajuns să mă încurc cel mai tare. Problema majoră a lor este că oferă răspunsuri variate și contradictorii pentru aceleași întrebări. Problemele mele sunt legate de seturile de caractere Unicode, restul până la 256 din formatul Engleză (gradul 2), pentru care nu găsesc codurile cu echivalența, iar ChatGPT mi-a oferit variante și variante care mai de care mai lipsite de încredere, așa că pe moment am renunțat la ele. Dacă are cineva corespondența simbol – Unicode, Meaning vă rog să mă contactați.

Discutie cu ChatGPT

Principala provocare a fost să înțeleg de ce sunt diferențe de reprezentare între Engleză și Română. De exemplu pentru Engleză literele mari sunt prefixate de cardul 000001 (~6) iar în română de cardul 000101 (~46). Aceasta este și propunerea articolului. De asemenea, există tehnici de scriere în care se scrie totul cu litere mari și literele mici sunt prefixate cu card specific.

Cel mai greu din punct de vedere tehnic mi-a fost să reprezint numerele dintr-un text. Numerele și în română și în engleză (grad 1) sunt prefixate de cardul 001111 (~3456) echivalentul # (diez) din setul de caractere ASCII.

Pentru asta am studiat separate descompunerea unui text în litere, apoi ca să-l pot compara cu litera anterioară sau următoare l-am generat în coloană separate. Am identificat așadar când apare prima literă într-o coloană și în acest caz i-am introdus un # (diez).

Formula din D7: =IF(ISNUMBER(–B7);IF(ISNUMBER(–C7);B7;”#”&B7);B7)

Pentru a descompune un text în fiecare literă a sa, am folosit funcția MID() cu SEQUENCE()

Formula din B7: =MID(B4;SEQUENCE(LEN(B4));1)

Ca să pot ulterior să o folosesc într-o singură funcție cu LET() a trebuit să pun cele două coloane pe o singură coloană, în format linie cu line (rows) apoi să le transform într-un nou tabel cu Wraprows() ca să pot să aplic fiecărei linii formula inițială din D7 folosind funcția BYROW().

Surpriza a fost că în momentul în care am încercat să le unific, opțiunea de TOCOL() din două variabile de tip coloană nu funcționează, așa că a trebuit să unesc textul celor două coloane în formatul: col1&col2 (rezultat în L6) după care să aplic o altă funcție decât MAP() sau BYROW() care nu funcționează pentru splitare. Astfel ca să pot splita o coloană în mai multe coloane (linie cu linie) a trebuit să construiesc funcția din M6:

Care mi-a permis să fac un tabel cu două coloane și căruia să-i pot aplica un BYROW() cu funcția din D7.

=LET(
Data; L6#;
LenData; LEN(Data);
Rows; COUNTA(Data);
NumCols; 2;
Tabel; SEQUENCE(Rows; NumCols; 1; 1);
CharIndex; MOD(Tabel - 1; LenData) + 1;
CharPosition; INT((Tabel - 1) / LenData) + 1;
INDEX(MID(Data; CharIndex; 1); CharPosition; SEQUENCE(1; NumCols))
)

A fost hard dar sper să se fi meritat și să fie de ajutor cuiva!

Pentru întrebări și comentarii puteți folosi secțiunea dedicată din site!

O zi luminoasă tuturor!

Blog la WordPress.com.

SUS ↑