Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6f29a5bce4 |
@@ -0,0 +1,33 @@
|
||||
# Plant3D usage from XLSX
|
||||
|
||||
Source is read-only. Only Plant3D sheets are analyzed; other sheets are ignored.
|
||||
|
||||
XLSX files: 151
|
||||
Temporary XLSX ignored: 0
|
||||
Files with Plant3D: 148
|
||||
Files without Plant3D: 3
|
||||
Files parsed: 148
|
||||
Files failed: 0
|
||||
Candidate rows examined: 16713
|
||||
Unique events: 0
|
||||
Duplicates: 0
|
||||
Rejected rows: 16716
|
||||
Date range:
|
||||
Unique plugins: 0
|
||||
Unique computers: 0
|
||||
Most used plugin:
|
||||
Most active computer:
|
||||
Source modified: NO
|
||||
|
||||
The Plant3D tables contain plugin and date fields but no computer-name column. The user field was not substituted for computer and was not published. Rows without a computer are rejected with COMPUTER_NOT_FOUND.
|
||||
|
||||
Top plugins:
|
||||
- нет валидных событий
|
||||
|
||||
Top computers:
|
||||
- нет валидных событий
|
||||
|
||||
Repeat:
|
||||
./tools/plugin-usage/Build-Plant3DExcelUsageMatrix.ps1 -SourceRoot C:/dev/TEMP/CheckPlugin -SheetName Plant3D -OutputDirectory ./migration/audits/plugin-usage-plant3d-xlsx-20260731
|
||||
|
||||
SourceFile values are anonymized as source-0001.xlsx. Project numbers, names, users and paths are not stored.
|
||||
@@ -0,0 +1 @@
|
||||
ComputerName,ComputerNameNormalized,TotalLaunches,UniquePlugins,FirstLaunch,LastLaunch,ActiveDays,MostUsedPlugin,MostUsedPluginLaunches
|
||||
|
@@ -0,0 +1 @@
|
||||
Plugin
|
||||
|
@@ -0,0 +1 @@
|
||||
Plugin,TotalLaunches,Computers,FirstLaunch,LastLaunch
|
||||
|
@@ -0,0 +1 @@
|
||||
PluginName,PluginNameNormalized,TotalLaunches,ComputerCount,FirstLaunch,LastLaunch,ActiveDays,ActiveMonths,MostActiveComputer,MostActiveComputerLaunches,ShareOfAllLaunches
|
||||
|
@@ -0,0 +1 @@
|
||||
EventId,PluginName,PluginNameNormalized,LaunchDateTime,LaunchDate,LaunchMonth,ComputerName,ComputerNameNormalized,SourceFile,SourceSheet,SourceRow,ParseRule,DuplicateCount
|
||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,152 @@
|
||||
"SourceFile","HasPlant3DSheet","ActualSheetName","RowCount","ColumnCount","Headers","SHA256","ParseResult","RejectedRows"
|
||||
"source-0001.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","A15A619FCBD036043644B235D1B5116C019838A42091CA6A451CD82DFCC41749","PARSED","1"
|
||||
"source-0002.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","A5B3F1451F88798417B3621F6BC6690BC0B1BA94E8F69B75BB4C6CB961B29BFB","PARSED","1"
|
||||
"source-0003.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","1DAA47089E28D62C9DF05541266ECEF512AACF87248BDA4576F42346EA6BE543","PARSED","1"
|
||||
"source-0004.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","B5AA0708B2C97B8F6AA13E4DA09C9FC4B205BB2A44D6A6993E7DB0ED26F9CEA5","PARSED","1"
|
||||
"source-0005.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","310124BF67ED7185513C834FBF3BC96A0AB243CF5114A41E2F78CE383D04F15F","PARSED","1"
|
||||
"source-0006.xlsx","False","","0","0","","484B6D563FFC782565DE9FE7AFBA18406017627D192CA2C3789EF8CEA63E20CE","SHEET_NOT_FOUND","1"
|
||||
"source-0007.xlsx","False","","0","0","","E5C9642AEA336BB0040B2FA290AAFD723AB6CE6F04519C5A003AAB927270F6C3","SHEET_NOT_FOUND","1"
|
||||
"source-0008.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","0323A416C468D838726E5792D887A7F9A381B2A1C13C65A340C57D472CCD8441","PARSED","1"
|
||||
"source-0009.xlsx","True","Plant3D","6","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","3CE17A1F2C385F2D3E8FC288D4342026FA329894C2FFD292521A94F8ECEC5FE8","PARSED","5"
|
||||
"source-0010.xlsx","True","Plant3D","414","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","A28C34A53E3D3342A20E013F1C8ECB0535369386C8A384F72DC2FB8A8EE22028","PARSED","413"
|
||||
"source-0011.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","F1B81195DA589C392940461EFFB4241A1531B1DA70BFC547896366AB94626473","PARSED","1"
|
||||
"source-0012.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","2C3506BA50204A3E8A1E42E0B466587103F80C8F8BEE692F27ED1FD2A7977E43","PARSED","1"
|
||||
"source-0013.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","BF74975CF82BB0CEB2CE6BF005A679BE2514D33A9E7F145DFCF91ED261A875B6","PARSED","1"
|
||||
"source-0014.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","7D2AE6636424016E60AF73B6826F4D9992A0A20356593C7D5D1034E3EBA47173","PARSED","1"
|
||||
"source-0015.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","D60671EADF93813991C84959F6C3E9CFEEB60F8F44522A6DB27FE64C0CCD8B7A","PARSED","1"
|
||||
"source-0016.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","A2B3F6E746DF732AA7FF721BCEE5A4C44442FC74851AE8ECA112B19D87671774","PARSED","1"
|
||||
"source-0017.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","B9430EC9C2BD7E6231F1A27390F63241111844956B6A32C01FADA6E8C0CB33AA","PARSED","1"
|
||||
"source-0018.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","1945DBF7EDD39F7F66605465E72C61FD405A1196D66DEA146E49D04DB8C2BF39","PARSED","1"
|
||||
"source-0019.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","1432526CC6D04A23B0AFFD7F0D7758D95CBC801ECC80CC868100A9849B8DFA05","PARSED","1"
|
||||
"source-0020.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","EF46F7969E767613029508068B0389A70F78B7781DEB1B1D5B57A55368CE14BF","PARSED","1"
|
||||
"source-0021.xlsx","True","Plant3D","1","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","2661112A136177954233F1D2AAD0ADA66DFBF0F8BC4FDF7845DF8B4C4604F431","PARSED","0"
|
||||
"source-0022.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","32637F9E79E4DD99E894B0920945135A3CB17A140A82596E1D02C9309F73FC39","PARSED","1"
|
||||
"source-0023.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","9E4660630442D118F09FCB11DBE975E25433197A8A5DFB12CC612C153E0F725E","PARSED","1"
|
||||
"source-0024.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","2BBF8C9E52E7B98ACE642BB19D16F3E3CC2F376E39A05E53BF992FF9050B8A1E","PARSED","1"
|
||||
"source-0025.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","A1325DC1797468286A02EDE3733DF8219B254E916154D31F34F4B461B6D2BC80","PARSED","1"
|
||||
"source-0026.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","FB1E886E31C2FB3D52CA0DBBD9E74CD091938B57E7C6F6FCF4966A7FE704392C","PARSED","1"
|
||||
"source-0027.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","C4FEC6A05FB2720D6C4341B8735C85900A8AA15805C5CE245E551C5FFA4EEBF8","PARSED","1"
|
||||
"source-0028.xlsx","True","Plant3D","56","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","66B28C7AB727BE7F77491313B75FB62F498C39500DE1CFB41C54A78EB184DFA1","PARSED","55"
|
||||
"source-0029.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","5F8D42AD0580CFD7F4CB407B45A1B7E4D4F26D9A04A2ADF7DDA7028499BD2146","PARSED","1"
|
||||
"source-0030.xlsx","True","Plant3D","90","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","F512D38F97E6848FFA80D30D226E8E79B6422AE96096D3B137A8D18D9C7283DD","PARSED","89"
|
||||
"source-0031.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","670D5DA7859B4FAE24EB4F5929939786865CD2B32C7FE829B8C553A74AAF82F8","PARSED","1"
|
||||
"source-0032.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","F08A03A625EBE9807A89BDD9357C92A1475AE7F19A5A3B488B3E8D7356A0D981","PARSED","1"
|
||||
"source-0033.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","0532B42C2AB5F10B2900A137D8C72745DACDE4EDF8C9612628E07CD388C9FC92","PARSED","1"
|
||||
"source-0034.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","205F5F22C7E7DD5C9F04B9CA730BC3E79A23A561E280838C62AC4B79741462D5","PARSED","1"
|
||||
"source-0035.xlsx","True","Plant3D","252","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","7A93BB9B4F04A534D1ABE7B36118288A5B6BA799E829B75B73C8DECAAD78D22C","PARSED","251"
|
||||
"source-0036.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","AB6211135C2391355AEB089B4893A2485869B94D9D4AFFE73936ED59C458676D","PARSED","1"
|
||||
"source-0037.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","08EFD4B8B47E13F5F7F1621B884EE7D75CA060C28F7D6521C0D5BC4EABC79A32","PARSED","1"
|
||||
"source-0038.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","514E2773029F9D5F827A3CDE7EC28F1F466C98ACBAABD65729FE69CE586DE0A8","PARSED","1"
|
||||
"source-0039.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","C199078B83D9FE0D78DF631A1534B6308CE801E4CE1AB61404BE33F039C728F6","PARSED","1"
|
||||
"source-0040.xlsx","True","Plant3D","3","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","C7BF9E922FF6813037E20C4AFF1B37FA6CEFB275F628BC15E5CFAC8DF374F89E","PARSED","2"
|
||||
"source-0041.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","BE31C9D8AC380F283989D5BA048ECB803111AB9599B8E2698834B5B4891E623C","PARSED","1"
|
||||
"source-0042.xlsx","True","Plant3D","586","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","2865FF71486B4BD98B0B6B30D92E05F21E483DC71C52C7D77C00760D889CDDB4","PARSED","585"
|
||||
"source-0043.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","3F73CDB5FB6F42172E1D23AC7B63EAB3764E8A97A6000B7D3678F896CBDD58BF","PARSED","1"
|
||||
"source-0044.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","FDD351196C3D124CCA31AFDBEF582DCBFE76C88E4119CF3601BB7D1D0B9EAAFE","PARSED","1"
|
||||
"source-0045.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","7DA92F660D6F73EC0333B4E637819DB88ADC6E40A7D2E2E9D780D1E7851D4025","PARSED","1"
|
||||
"source-0046.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","EF3485449D9F5CEF104B14FE4D16BFDC3A27199C6117732D15CFC994F361F32F","PARSED","1"
|
||||
"source-0047.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","170D835A968A0590ACEA2909AE9DD204A8A7B2B01FD4254FBFD30F7216B2D4C4","PARSED","1"
|
||||
"source-0048.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","AAC46741C97CA9D5DBBADA8815D0D894F99F37F1CF6CD0FF6E2D1F090D3AD920","PARSED","1"
|
||||
"source-0049.xlsx","True","Plant3D","734","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","F49CD86C04D7CFDA8F1FE0FB6131F9F28A86916A6C9012D54B116E9F272C8ABE","PARSED","733"
|
||||
"source-0050.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","A024F33FD3CD408C7FC62C59D6511F2FB8CA257DF5872A3C793875AD700F0623","PARSED","1"
|
||||
"source-0051.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","63FC0734C4B58165B3C53E06320ACC86A8D9B11F1B71EE4796071E462C291794","PARSED","1"
|
||||
"source-0052.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","170D835A968A0590ACEA2909AE9DD204A8A7B2B01FD4254FBFD30F7216B2D4C4","PARSED","1"
|
||||
"source-0053.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","86AF67FAC7778F3EAEBF51BCF0C643387CCBFADA9020D48B0C0B7403E52E45C4","PARSED","1"
|
||||
"source-0054.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","76EDCFF3616F370F7EBAF4917EB430B9C606DCAC88B2782A11511B725ED30E84","PARSED","1"
|
||||
"source-0055.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","1C1116CDE1D4D33F5B5C03710999EB74D546E9FD21780DF4F8BFA51F7683FFD1","PARSED","1"
|
||||
"source-0056.xlsx","True","Plant3D","25","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","CBAA90125E90F981FC9C9E7C1866C4D7A4AC80020D02B939E3010BA76D5889A5","PARSED","24"
|
||||
"source-0057.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","F50FF129D9F408BD431DC7D9997F675037E3822ED0A2F3EEDDDC37D2E783A2C2","PARSED","1"
|
||||
"source-0058.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","6B378A5C23A90C23762B9257C36E5DFC6357A7A924E8A435BFA97CD438E94B66","PARSED","1"
|
||||
"source-0059.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","E4736511A4CE16692ADCF5DF17C006A0CA6BD10E135DFFC4770EA1CCA1FB9EF0","PARSED","1"
|
||||
"source-0060.xlsx","True","Plant3D","895","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","DCE700252D4065DF7A03B22FED55E36D75B468DA6207439E968DAEFDB05270F8","PARSED","894"
|
||||
"source-0061.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","F1221EBEAA1FAEFFCCC41A921F55378B1E301806DE862A71A30EC101B37A74E9","PARSED","1"
|
||||
"source-0062.xlsx","True","Plant3D","460","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","7727E99AC47171CDA1F590B2E6380BC96F7DED676AA335637CE1436612B52D56","PARSED","459"
|
||||
"source-0063.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","CA8F71B9B2ECF4B27B7B581E3E4BA770873B1E73EEEFEB538ED441C5C8757A0B","PARSED","1"
|
||||
"source-0064.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","C7A1E4C8CB9CB27D05C62D89133A40665F791484431B192A73F59B8F9A6DB29E","PARSED","1"
|
||||
"source-0065.xlsx","True","Plant3D","237","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","89A2AD33216311E5982DE7D311A4B7BBA5F9120B74B3F45EE480512BDACA650B","PARSED","236"
|
||||
"source-0066.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","AAEA49E5B294B77A9C1ABD2530E84BCE3B5814CEAA8D43638D921D03ADB0B3D7","PARSED","1"
|
||||
"source-0067.xlsx","True","Plant3D","117","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","23AD7BE9E3CD38A6141171BC7848CA024AD9DDEA1613719781F8E4F0A695A4EB","PARSED","116"
|
||||
"source-0068.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","ADE70DE40D2ECBBDF6C92CAFAC598A4E79FB1EF4B42B7FD29B86358EDFB882FB","PARSED","1"
|
||||
"source-0069.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","9F995F5F40ABAD9FA72913BD8CD66D4D94252A247ABA1B6AAF1F618C02CC8807","PARSED","1"
|
||||
"source-0070.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","954F040E98D6D0AB8DA5E3D9226C2F2DDC1320CFA25FA84355346406E89A5562","PARSED","1"
|
||||
"source-0071.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","861D3B078EE1520FAC14F8BAB765C804DA233545B46C548EACC0894FED45CECF","PARSED","1"
|
||||
"source-0072.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","7CC2D143DCDA82A368F478D246086934AE20BC21B8EBCD19B17488D6A1B5C9DA","PARSED","1"
|
||||
"source-0073.xlsx","True","Plant3D","1","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","658B087B7CDB15130678A5F58E4FA1B1FA5688457FA2FA03DFA7A218D3EA0CCC","PARSED","0"
|
||||
"source-0074.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","D8039752750039DD7A8DA647C21087A12944F4ACDCD636D27BD8624D86375125","PARSED","1"
|
||||
"source-0075.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","CC9C45987C6DA9646FC4FD771F8D8B6C2F3F466C609203C2AAE31C1AD79C595B","PARSED","1"
|
||||
"source-0076.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","9FE880A33CA691260B76A025145339D1757B8295942323DC1A24020B9D2E1BE1","PARSED","1"
|
||||
"source-0077.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","69233E373BA94FF1D0F5BEBAE67880BD34BA873992875344E1458254B64B9E8A","PARSED","1"
|
||||
"source-0078.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","D7C5B3583FA52CF6D4DDB4B8D673BE12ECFA7C18C40CED86679D691E3D6E32B6","PARSED","1"
|
||||
"source-0079.xlsx","True","Plant3D","697","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","EFD4FC75BDED4E45A774945511D527F71433C58EC86C4F20275AC2D97CE7AAA1","PARSED","696"
|
||||
"source-0080.xlsx","True","Plant3D","287","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","222E65CCAB8CA101B3DA836BB2D87FBC77A46B309066270A5A13D48C5FDC8E00","PARSED","286"
|
||||
"source-0081.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","35044B7D3E03E7C67E7C04AA532E307522226A4CE7D50A51107B4CC2B7AE3117","PARSED","1"
|
||||
"source-0082.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","BF54E9EC75A0716BC4AD71E310AC8558E3EA7FF4FF1AE7616FB6C546F3D05D75","PARSED","1"
|
||||
"source-0083.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","C2D6E13731016E523F582D065480F385E3D8EFC9379C6CB20A8FEC288330BD33","PARSED","1"
|
||||
"source-0084.xlsx","True","Plant3D","1860","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","ED0BC02534ECB9636BE0C2268926942C8DEB9ADDC75823CF6A1E241E188E96DF","PARSED","1859"
|
||||
"source-0085.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","30B54423173405FB2179C2F0C1532DEF28A292A7E3249C5483CED353F692691A","PARSED","1"
|
||||
"source-0086.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","BE7148B01F6BF466650D93ED1A1CFF736AFC5DF43567FA4D62C319ED0739863B","PARSED","1"
|
||||
"source-0087.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","27EA9A83CEDB02328F8E99D914CAB7EC9325313458D36678FC14994F028A7C66","PARSED","1"
|
||||
"source-0088.xlsx","True","Plant3D","152","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","35C2F37E1453CC52B85BFAA335695931D469844C660CDBE8356FF60FA5EDC094","PARSED","151"
|
||||
"source-0089.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","FF6B2808D71FD697AC2AD83400152E258EE428FF50CF00D22915AE70CA4F2D19","PARSED","1"
|
||||
"source-0090.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","4C5AB590CDC6F764326B8DCE845E0DBFB51C9A8710DCA65671173A06B1F4C8BE","PARSED","1"
|
||||
"source-0091.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","9A68D1C2B05E2A1AE7DC08F56A203F12094064DC90CF4A753E6B024944058953","PARSED","1"
|
||||
"source-0092.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","AA4CF707135416550D390D59275F4EF96597CA413553ED998BAD249266C1BB0C","PARSED","1"
|
||||
"source-0093.xlsx","True","Plant3D","60","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","6E9634C35B174D2CA2BF67E7E5D5A5D322E8E33366231D419927335D67118158","PARSED","59"
|
||||
"source-0094.xlsx","True","Plant3D","810","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","7826F33C15EA6164E46A9BB762DDA073ED113B918F81E3BFF9BACBD4F9E9862A","PARSED","809"
|
||||
"source-0095.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","4FE1B8234D58BB533E118659489AD5497E17EC58C935FB467B78FE00AE868782","PARSED","1"
|
||||
"source-0096.xlsx","True","Plant3D","3","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","AC2B780B38BBF7B0BDFC6F3134633536A4A64DB3A2C71F010079A99ABC698EBF","PARSED","2"
|
||||
"source-0097.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","FF6A99D2F4042CDEDC0D8AB2863FCA5B74128D9CD39A6FF42E4DCA3CFC8CF62B","PARSED","1"
|
||||
"source-0098.xlsx","True","Plant3D","91","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","CFDF4380ABFF2899C15963155D1AC991CFDC2E0F6F5615191DC983F7CE8E3708","PARSED","90"
|
||||
"source-0099.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","ACF37ECD1F508F39F352C3112113F6214741032F642012233F7C0EB71D57FAE3","PARSED","1"
|
||||
"source-0100.xlsx","True","Plant3D","1039","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","BE19C25F151B4525E0058F7C974B250AFEC651585F71A2B0BC9A28C6D2639521","PARSED","1038"
|
||||
"source-0101.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","5F8D42AD0580CFD7F4CB407B45A1B7E4D4F26D9A04A2ADF7DDA7028499BD2146","PARSED","1"
|
||||
"source-0102.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","219ACB4310303A5EE9E5A825998AF9012AD80F597F693B730583ACEC5856B935","PARSED","1"
|
||||
"source-0103.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","96074CB9DECE06172FD88185CF379830582046A83C7405AD7B41D7F6196BD0C0","PARSED","1"
|
||||
"source-0104.xlsx","True","Plant3D","74","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","16D424D7B51535AFF74B02F1FAA113E35A501E7A5C6E991382853FAB0F14AB02","PARSED","73"
|
||||
"source-0105.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","2BD63E06782C45CAF3A77C301F980ABE6421C098E549DDD639918894987CFD4B","PARSED","1"
|
||||
"source-0106.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","23F20D79B82DA3BE0E979AB55939B308F5CE35264C687A13FAF0B0EFA31912C9","PARSED","1"
|
||||
"source-0107.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","1843EDAF7DBFB71036D62B9C80DBC256199969EF64B1881E9E5A051B1EADEDD5","PARSED","1"
|
||||
"source-0108.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","BE04A1D538CB18E1F909E0F0F911AC7D8DE0C614FD107E5F9209E843F2AE1311","PARSED","1"
|
||||
"source-0109.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","205F5F22C7E7DD5C9F04B9CA730BC3E79A23A561E280838C62AC4B79741462D5","PARSED","1"
|
||||
"source-0110.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","1A04C1D1FEC0D6DE24AE5B59A303FAC8617D6DCB7C79BA61F493797E249F6BE7","PARSED","1"
|
||||
"source-0111.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","69D6ECE741A1CE49B9188F9191F04DD49B8FB1D36AE79492D302DAF8BC55DE0D","PARSED","1"
|
||||
"source-0112.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","67E4B2F304BD98BC953742C319AD9FDC60E1DDF809317D264AB92B5DD496D153","PARSED","1"
|
||||
"source-0113.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","5207B2F0DC0DB9C5399A32A1505310665180EC74D6A26015475986DCBF379563","PARSED","1"
|
||||
"source-0114.xlsx","True","Plant3D","107","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","BB0EA311890606D735E090E3CC009275EE1EA0430A861A36E1B5B887619FB9BB","PARSED","106"
|
||||
"source-0115.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","90AF2345A620F5735BA47A7B0A6355CF1FC6ACD508DD566123B20F7FD3E40BCF","PARSED","1"
|
||||
"source-0116.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","B5B54A5399281FE2F6439D499496EF27B110BBB1DE8008428F80BD5E3FE9B6E7","PARSED","1"
|
||||
"source-0117.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","777C7A38D2F97998426FB4E6A39AA7C4ADA7343D48C00427DEA58FBA915B3D67","PARSED","1"
|
||||
"source-0118.xlsx","True","Plant3D","3","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","AC66A34DA4BA02E8452B1CA0CDCFF381AA7F56C2ECF206C6D3E39DC49DFD8B86","PARSED","2"
|
||||
"source-0119.xlsx","True","Plant3D","703","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","630481E3722EF0E4F271C812FCB686BFEC679EC2A90B1CE60929FA178276B746","PARSED","702"
|
||||
"source-0120.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","217E8F2CE5C0E50FFECDFDC69C99629EFF86F8F1C5820B804472CCBB96C83693","PARSED","1"
|
||||
"source-0121.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","606068897D6B8B66ABABDF0F123679A46864CCD8D3D8F7A64C5DB8242B910AA7","PARSED","1"
|
||||
"source-0122.xlsx","False","","0","0","","775B72ABA7A5F3277F857C4431A9795192451621DDDA9E568952EE5FC4B818E2","SHEET_NOT_FOUND","1"
|
||||
"source-0123.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","77C0DBDA49BCF2A61E1E8661FE56069B13F5CD76372B60CCBCB4FED4D9FCC300","PARSED","1"
|
||||
"source-0124.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","11E3CB994067C2944C72783818094A3B0070E9B20F16E65E4DF5EEC4BC7D4BEF","PARSED","1"
|
||||
"source-0125.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","A8D15E45344B4F9914F28EB471C74B90F4C8AB09F588C5932ADEC6A69EF3A1F1","PARSED","1"
|
||||
"source-0126.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","973258780339702C9EAF6E67B69C8835B5585E00D21764598B619A8490EF6334","PARSED","1"
|
||||
"source-0127.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","B276743CAB8202E42B5E6578DCFD33FAC968CC809EF258D3D083D1858D42FF9A","PARSED","1"
|
||||
"source-0128.xlsx","True","Plant3D","3128","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","88200AC6044F16B2B18F5448F6B4BC5BAF6E1F9EE5446E1FD30EB321AC2B8BDC","PARSED","3127"
|
||||
"source-0129.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","78A70F71CF77C11855ADA80A805FAD5F04FF8B5D55516FC6565C1FB86E46D4D5","PARSED","1"
|
||||
"source-0130.xlsx","True","Plant3D","65","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","D934BC7DB6C68A6458FFFE801C61B622BDCB10979CCB3B22431867A346DF3559","PARSED","64"
|
||||
"source-0131.xlsx","True","Plant3D","1027","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","E0192943F2454E18F72092D794D3E73A55536B7757269638BAD922BBF7E58DCF","PARSED","1026"
|
||||
"source-0132.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","10EB6F3BB853E29C25D5C7781F7DBE32AB66DEFCF74F33A0E041326DB3E058C1","PARSED","1"
|
||||
"source-0133.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","013EBC9D96D0A2330A708C04C715A97830337DF0E85A13A46B9CEB46B641A662","PARSED","1"
|
||||
"source-0134.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","480B287CB70F44135B538D406934BC84D48A9907EAC15BCDBE566606F9459814","PARSED","1"
|
||||
"source-0135.xlsx","True","Plant3D","1970","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","6213EE80A8303E74E0C5D8D0706F4BF18BA8C66CF7D521269D83342DC129456C","PARSED","1969"
|
||||
"source-0136.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","F2351A9EE055766BA23389341EDE4F646EF93A6F4EC5D643FABDC938D6856741","PARSED","1"
|
||||
"source-0137.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","7BF721DA2ACE12EEBEAE8B810BB36E1609A716312D57123AB8DE5E3AB88A2C67","PARSED","1"
|
||||
"source-0138.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","B5EFA1E2A03AD1E58DE3A8BD8E654DAE2D6D3BEE25ABD83A1F2DAAA7D1ACBBA0","PARSED","1"
|
||||
"source-0139.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","D01E5620808DC870F30C7A2F8FBB142989BC64B47ACA75C33EB8891261210D61","PARSED","1"
|
||||
"source-0140.xlsx","True","Plant3D","499","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","1E4BA218B03A56523525B6B62FCFA2381CC6C142018426EFB8BC12FD8B5B248E","PARSED","498"
|
||||
"source-0141.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","B39C734C901C75D4E297A7F1044068B28FA2459A2ECD3518BB9FE4B325052344","PARSED","1"
|
||||
"source-0142.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","A69931EA29521E1AB9CE9EEFAD29E07687B57A6B35CBC0023FD8CEAB706BF2AA","PARSED","1"
|
||||
"source-0143.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","6BF892D6DB59C80850AD3FD316CBC6B6BAAB93AD54D1B7273C525C26141405EE","PARSED","1"
|
||||
"source-0144.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","4940E6C9CBB4C3B8D327F463A3EADA1FEBD622E8065D038D97364CA99D1D2D7F","PARSED","1"
|
||||
"source-0145.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","106F64274F9146D16FC5915A19FE112C287CB91FBE1F466C25D535746A3398AE","PARSED","1"
|
||||
"source-0146.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","EFF26E58F20FCEE544B341129C608788C6A3D96C1BDCD22AF34B6D10BE220492","PARSED","1"
|
||||
"source-0147.xlsx","True","Plant3D","181","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","55846ECDE3A730B781564A2059D3DAC56536EC3AAEF69B09BB07178AC8720212","PARSED","180"
|
||||
"source-0148.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","94278E1422D937D2C6D365036C35732C5D9C24BF70AB51ED78606668D848AB9D","PARSED","1"
|
||||
"source-0149.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","85B5D8D2537326FA82CFCBA6158AE0F852E0FB7DA4D342C1507CEC4F233D9681","PARSED","1"
|
||||
"source-0150.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","CF4DB120F80B11598077A842CD458703C2938D010C773D5A5C6E41AE707950C3","PARSED","1"
|
||||
"source-0151.xlsx","True","Plant3D","2","6","Файл;Пользователь;Плагин;Дата;Количество запусков;Номер проекта","F6DE7BCCBCC3B6B4CEC6FA81F0C5F17DE7E0725E8AE7BF6384798429C431A38D","PARSED","1"
|
||||
|
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"XlsxFilesFound": 151,
|
||||
"TemporaryXlsxIgnored": 0,
|
||||
"FilesWithPlant3DSheet": 148,
|
||||
"FilesWithoutPlant3DSheet": 3,
|
||||
"FilesParsed": 148,
|
||||
"FilesFailed": 0,
|
||||
"RawRows": 16713,
|
||||
"ValidRows": 0,
|
||||
"UniqueEvents": 0,
|
||||
"Duplicates": 0,
|
||||
"RejectedRows": 16716,
|
||||
"DateRange": "",
|
||||
"UniquePlugins": 0,
|
||||
"UniqueComputers": 0,
|
||||
"MostUsedPlugin": "",
|
||||
"MostActiveComputer": "",
|
||||
"SourceModified": "NO"
|
||||
}
|
||||
@@ -0,0 +1,292 @@
|
||||
param(
|
||||
[Parameter(Mandatory=$false)][string]$SourceRoot = 'C:\dev\TEMP\CheckPlugin',
|
||||
[Parameter(Mandatory=$false)][string]$SheetName = 'Plant3D',
|
||||
[Parameter(Mandatory=$false)][string]$OutputDirectory = 'C:\dev\autodesk\migration\audits\plugin-usage-plant3d-xlsx-20260731'
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
Add-Type -AssemblyName System.IO.Compression.FileSystem
|
||||
$utf8Bom = New-Object System.Text.UTF8Encoding($true)
|
||||
$utf8 = New-Object System.Text.UTF8Encoding($false)
|
||||
$nsMainUri = 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'
|
||||
$nsRelUri = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'
|
||||
$nsPkgRelUri = 'http://schemas.openxmlformats.org/package/2006/relationships'
|
||||
$outputEvidence = Join-Path $OutputDirectory 'evidence'
|
||||
New-Item -ItemType Directory -Force -Path $outputEvidence | Out-Null
|
||||
|
||||
function Get-XmlEntry([IO.Compression.ZipArchive]$Zip, [string]$Name) {
|
||||
$entry = $Zip.GetEntry($Name.TrimStart('/'))
|
||||
if ($null -eq $entry) { return $null }
|
||||
$reader = [IO.StreamReader]::new($entry.Open())
|
||||
try { return [xml]$reader.ReadToEnd() } finally { $reader.Dispose() }
|
||||
}
|
||||
|
||||
function Get-ColumnNumber([string]$Reference) {
|
||||
$letters = ([regex]::Match($Reference, '^[A-Z]+')).Value
|
||||
$number = 0
|
||||
foreach ($letter in $letters.ToCharArray()) { $number = $number * 26 + ([int][char]$letter - 64) }
|
||||
return $number
|
||||
}
|
||||
|
||||
function Normalize-Header([string]$Value) {
|
||||
if ($null -eq $Value) { return '' }
|
||||
return (($Value.Trim().ToLowerInvariant()) -replace '[\s_\-\.]+','')
|
||||
}
|
||||
|
||||
function Normalize-Plugin([string]$Value) {
|
||||
$v = if ($null -eq $Value) { '' } else { $Value.Trim() }
|
||||
return (($v -replace '(?i)\.(dll|exe)$','').Trim().ToUpperInvariant())
|
||||
}
|
||||
|
||||
function Normalize-Computer([string]$Value) {
|
||||
if ($null -eq $Value) { return '' }
|
||||
return $Value.Trim().ToUpperInvariant()
|
||||
}
|
||||
|
||||
function Get-SharedStrings([IO.Compression.ZipArchive]$Zip) {
|
||||
$xml = Get-XmlEntry $Zip 'xl/sharedStrings.xml'
|
||||
$values = [System.Collections.Generic.List[string]]::new()
|
||||
if ($null -eq $xml) { return $values }
|
||||
$manager = New-Object Xml.XmlNamespaceManager($xml.NameTable)
|
||||
$manager.AddNamespace('m',$nsMainUri)
|
||||
foreach ($item in $xml.SelectNodes('//m:si',$manager)) { $values.Add((($item.SelectNodes('.//m:t',$manager) | ForEach-Object InnerText) -join '')) }
|
||||
return $values
|
||||
}
|
||||
|
||||
function Get-CellText($Cell, $Manager, $SharedStrings) {
|
||||
if ($null -eq $Cell) { return '' }
|
||||
$inline = $Cell.SelectSingleNode('./m:is',$Manager)
|
||||
if ($null -ne $inline) { return (($inline.SelectNodes('.//m:t',$Manager) | ForEach-Object InnerText) -join '') }
|
||||
$value = $Cell.SelectSingleNode('./m:v',$Manager)
|
||||
if ($null -eq $value) { return '' }
|
||||
$raw = $value.InnerText
|
||||
if ([string]$Cell.t -eq 's') {
|
||||
$index = 0
|
||||
if ([int]::TryParse($raw,[ref]$index) -and $index -lt $SharedStrings.Count) { return $SharedStrings[$index] }
|
||||
}
|
||||
return $raw
|
||||
}
|
||||
|
||||
function Get-DateValue([string]$Text, [bool]$Numeric, [int]$Style, $DateStyles) {
|
||||
if ([string]::IsNullOrWhiteSpace($Text)) { return $null }
|
||||
$dateLike = $false
|
||||
if ($Numeric -and $DateStyles.Contains($Style)) { $dateLike = $true }
|
||||
if ($dateLike) {
|
||||
$serial = 0.0
|
||||
if ([double]::TryParse($Text,[Globalization.NumberStyles]::Float,[Globalization.CultureInfo]::InvariantCulture,[ref]$serial)) {
|
||||
return [pscustomobject]@{ Date = [DateTime]::FromOADate($serial); Rule = 'EXCEL_SERIAL_DATE' }
|
||||
}
|
||||
}
|
||||
$clean = ($Text.Trim() -replace '[Tt]',' ' -replace '[\u00A0]',' ' -replace '\s+',' ')
|
||||
$formats = @('yyyy MM dd HH:mm:ss','yyyy MM dd H:mm:ss','yyyy MM dd','dd.MM.yyyy HH:mm:ss','dd.MM.yyyy H:mm:ss','dd.MM.yyyy','dd.MM.yy HH:mm:ss','dd.MM.yy H:mm:ss','dd.MM.yy','yyyy-MM-dd HH:mm:ss','yyyy-MM-dd','dd/MM/yyyy HH:mm:ss','dd/MM/yyyy')
|
||||
foreach ($format in $formats) {
|
||||
$parsed = [DateTime]::MinValue
|
||||
if ([DateTime]::TryParseExact($clean,$format,[Globalization.CultureInfo]::InvariantCulture,[Globalization.DateTimeStyles]::AllowWhiteSpaces,[ref]$parsed)) {
|
||||
$rule = if ($format -match 'H|s') { 'TEXT_DATETIME' } else { 'DATE_ONLY' }
|
||||
return [pscustomobject]@{ Date = $parsed; Rule = $rule }
|
||||
}
|
||||
}
|
||||
$parsed = [DateTime]::MinValue
|
||||
if ([DateTime]::TryParse($clean,[Globalization.CultureInfo]::GetCultureInfo('ru-RU'),[Globalization.DateTimeStyles]::AllowWhiteSpaces,[ref]$parsed)) {
|
||||
return [pscustomobject]@{ Date = $parsed; Rule = if ($clean -match ':') { 'TEXT_DATETIME' } else { 'DATE_ONLY' } }
|
||||
}
|
||||
return $null
|
||||
}
|
||||
|
||||
function Get-DateStyles([IO.Compression.ZipArchive]$Zip) {
|
||||
$set = [Collections.Generic.HashSet[int]]::new()
|
||||
foreach ($i in 14..22) { [void]$set.Add($i) }
|
||||
$styles = Get-XmlEntry $Zip 'xl/styles.xml'
|
||||
if ($null -eq $styles) { return $set }
|
||||
$manager = New-Object Xml.XmlNamespaceManager($styles.NameTable); $manager.AddNamespace('m',$nsMainUri)
|
||||
$dateWords = 'yy|yyyy|mm|dd|hh|ss|am/pm'
|
||||
$formats = @{}
|
||||
foreach ($format in $styles.SelectNodes('//m:numFmts/m:numFmt',$manager)) { $formats[[int]$format.numFmtId] = [string]$format.formatCode }
|
||||
$index = 0
|
||||
foreach ($xf in $styles.SelectNodes('//m:cellXfs/m:xf',$manager)) {
|
||||
$id = [int]$xf.numFmtId
|
||||
if (($formats.ContainsKey($id) -and $formats[$id] -match $dateWords) -or ($id -ge 14 -and $id -le 22)) { [void]$set.Add($index) }
|
||||
$index++
|
||||
}
|
||||
return $set
|
||||
}
|
||||
|
||||
function Get-WorkbookSheet($Zip, [string]$WantedName) {
|
||||
$workbook = Get-XmlEntry $Zip 'xl/workbook.xml'
|
||||
$relationships = Get-XmlEntry $Zip 'xl/_rels/workbook.xml.rels'
|
||||
if ($null -eq $workbook -or $null -eq $relationships) { throw 'READ_ERROR: workbook metadata is missing' }
|
||||
$manager = New-Object Xml.XmlNamespaceManager($workbook.NameTable); $manager.AddNamespace('m',$nsMainUri); $manager.AddNamespace('r',$nsRelUri)
|
||||
$relManager = New-Object Xml.XmlNamespaceManager($relationships.NameTable); $relManager.AddNamespace('p',$nsPkgRelUri)
|
||||
$wanted = $WantedName.Trim().ToLowerInvariant()
|
||||
foreach ($sheet in $workbook.SelectNodes('//m:sheets/m:sheet',$manager)) {
|
||||
if ([string]$sheet.name.Trim().ToLowerInvariant() -eq $wanted) {
|
||||
$id = $sheet.GetAttribute('id',$nsRelUri)
|
||||
$rel = $relationships.SelectSingleNode("//p:Relationship[@Id='$id']",$relManager)
|
||||
if ($null -eq $rel) { throw 'READ_ERROR: worksheet relationship is missing' }
|
||||
$target = ([string]$rel.Target).TrimStart('/')
|
||||
if ($target -notmatch '^xl/') { $target = 'xl/' + $target }
|
||||
return [pscustomobject]@{ Name = [string]$sheet.name; Target = $target }
|
||||
}
|
||||
}
|
||||
return $null
|
||||
}
|
||||
|
||||
function Get-WorksheetRows($Zip, [string]$Target, $SharedStrings, $DateStyles) {
|
||||
$xml = Get-XmlEntry $Zip $Target
|
||||
if ($null -eq $xml) { throw 'READ_ERROR: worksheet is missing' }
|
||||
$manager = New-Object Xml.XmlNamespaceManager($xml.NameTable); $manager.AddNamespace('m',$nsMainUri)
|
||||
$rows = [System.Collections.Generic.List[object]]::new()
|
||||
foreach ($row in $xml.SelectNodes('//m:sheetData/m:row',$manager)) {
|
||||
$cells = @{}
|
||||
foreach ($cell in $row.SelectNodes('./m:c',$manager)) {
|
||||
$column = Get-ColumnNumber ([string]$cell.r)
|
||||
$raw = Get-CellText $cell $manager $SharedStrings
|
||||
$numeric = ([string]$cell.t -eq '' -or [string]$cell.t -eq 'n')
|
||||
$style = if ([string]$cell.s) { [int]$cell.s } else { 0 }
|
||||
$cells[$column] = [pscustomobject]@{ Text = $raw; Date = Get-DateValue $raw $numeric $style $DateStyles }
|
||||
}
|
||||
$rows.Add([pscustomobject]@{ Number = [int]$row.r; Hidden = ([string]$row.hidden -eq '1'); Cells = $cells })
|
||||
}
|
||||
return [pscustomobject]@{ Rows = $rows; ColumnCount = (($rows | ForEach-Object { if($_.Cells.Count){($_.Cells.Keys|Measure-Object -Maximum).Maximum}else{0} } | Measure-Object -Maximum).Maximum) }
|
||||
}
|
||||
|
||||
function Get-Cell($Row,[int]$Column) { if($Row.Cells.ContainsKey($Column)){return $Row.Cells[$Column].Text}; return '' }
|
||||
|
||||
function Find-Header($Rows) {
|
||||
$pluginAliases = @('плагин','названиеплагина','plugin','pluginname','module','command')
|
||||
$dateAliases = @('дата','время','датазапуска','датаивремя','date','time','datetime','timestamp','launchdate')
|
||||
$computerAliases = @('пк','компьютер','имяпк','computer','computername','machine','machinename','host','hostname')
|
||||
foreach($row in $Rows | Select-Object -First 30) {
|
||||
$map = @{}
|
||||
foreach($key in $row.Cells.Keys){$map[(Normalize-Header (Get-Cell $row $key))]=[int]$key}
|
||||
$plugin = ($pluginAliases | ? {$map.ContainsKey($_)} | Select -First 1)
|
||||
$date = ($dateAliases | ? {$map.ContainsKey($_)} | Select -First 1)
|
||||
$computer = ($computerAliases | ? {$map.ContainsKey($_)} | Select -First 1)
|
||||
if($plugin -and $date){return [pscustomobject]@{ Row = $row; PluginColumn = $map[$plugin]; DateColumn = $map[$date]; TimeColumn = if($map.ContainsKey('время')){$map['время']}elseif($map.ContainsKey('time')){$map['time']}else{$null}; ComputerColumn = if($computer){$map[$computer]}else{$null}; Rule='HEADER_ALIASES' }}
|
||||
}
|
||||
return $null
|
||||
}
|
||||
|
||||
function Get-Sha256([string]$Path) { return (Get-FileHash -LiteralPath $Path -Algorithm SHA256).Hash }
|
||||
function Get-RowHash([string]$SourceId,[int]$Row,[string]$Plugin,[string]$Date,[string]$Computer) { $text = "$SourceId|$Row|$Plugin|$Date|$Computer"; $sha = [Security.Cryptography.SHA256]::Create(); try { return (([BitConverter]::ToString($sha.ComputeHash([Text.Encoding]::UTF8.GetBytes($text)))) -replace '-','') } finally { $sha.Dispose() } }
|
||||
function Csv([object[]]$Rows,[string]$Path) {
|
||||
if($null -eq $Rows){$Rows=@()}
|
||||
if($Rows.Count -gt 0){$Rows | Export-Csv -LiteralPath $Path -NoTypeInformation -Encoding UTF8; return}
|
||||
$headers = switch ([IO.Path]::GetFileName($Path)) {
|
||||
'plugin-usage-events.csv' { 'EventId,PluginName,PluginNameNormalized,LaunchDateTime,LaunchDate,LaunchMonth,ComputerName,ComputerNameNormalized,SourceFile,SourceSheet,SourceRow,ParseRule,DuplicateCount' }
|
||||
'plugin-summary.csv' { 'PluginName,PluginNameNormalized,TotalLaunches,ComputerCount,FirstLaunch,LastLaunch,ActiveDays,ActiveMonths,MostActiveComputer,MostActiveComputerLaunches,ShareOfAllLaunches' }
|
||||
'pc-summary.csv' { 'ComputerName,ComputerNameNormalized,TotalLaunches,UniquePlugins,FirstLaunch,LastLaunch,ActiveDays,MostUsedPlugin,MostUsedPluginLaunches' }
|
||||
'plugin-pc-matrix.csv' { 'Plugin,TotalLaunches,Computers,FirstLaunch,LastLaunch' }
|
||||
'plugin-month-matrix.csv' { 'Plugin' }
|
||||
'rejected-records.csv' { 'SourceFile,SourceSheet,SourceRow,ReasonCode,DetectedPlugin,DetectedDateTime,DetectedComputer,RowHash' }
|
||||
'source-inventory.csv' { 'SourceFile,HasPlant3DSheet,ActualSheetName,RowCount,ColumnCount,Headers,SHA256,ParseResult,RejectedRows' }
|
||||
}
|
||||
[IO.File]::WriteAllText($Path, $headers + "`r`n", $utf8Bom)
|
||||
}
|
||||
|
||||
$files = @(Get-ChildItem -LiteralPath $SourceRoot -Recurse -File -Filter '*.xlsx' | Where-Object Name -notlike '~$*' | Sort-Object FullName)
|
||||
$eventsRaw = [Collections.Generic.List[object]]::new(); $rejected = [Collections.Generic.List[object]]::new(); $inventory = [Collections.Generic.List[object]]::new(); $fileIndex=0; $rawRowsExamined=0; $temporaryIgnored = @(Get-ChildItem -LiteralPath $SourceRoot -Recurse -File -Filter '~$*.xlsx' -ErrorAction SilentlyContinue).Count
|
||||
|
||||
foreach($file in $files) {
|
||||
$fileIndex++; $sourceId = ('source-{0:D4}.xlsx' -f $fileIndex); $beforeSize=$file.Length; $beforeTime=$file.LastWriteTimeUtc; $hash=Get-Sha256 $file.FullName
|
||||
$plant=$false; $sheetActual=''; $rowCount=0; $columnCount=0; $result='FAILED'; $rejectedBefore=$rejected.Count
|
||||
try {
|
||||
$zip=[IO.Compression.ZipFile]::OpenRead($file.FullName)
|
||||
try {
|
||||
$sheet=Get-WorkbookSheet $zip $SheetName
|
||||
if($null -eq $sheet) { $rejected.Add([pscustomobject]@{SourceFile=$sourceId;SourceSheet='';SourceRow='';ReasonCode='SHEET_NOT_FOUND';DetectedPlugin='';DetectedDateTime='';DetectedComputer='';RowHash=(Get-RowHash $sourceId 0 '' '' '')}); $inventory.Add([pscustomobject]@{SourceFile=$sourceId;HasPlant3DSheet=$false;ActualSheetName='';RowCount=0;ColumnCount=0;Headers='';SHA256=$hash;ParseResult='SHEET_NOT_FOUND';RejectedRows=1}); continue }
|
||||
$plant=$true; $sheetActual=$sheet.Name; $shared=Get-SharedStrings $zip; $dates=Get-DateStyles $zip; $worksheet=Get-WorksheetRows $zip $sheet.Target $shared $dates; $rowCount=$worksheet.Rows.Count; $columnCount=$worksheet.ColumnCount; $header=Find-Header $worksheet.Rows
|
||||
if($null -eq $header){$rejected.Add([pscustomobject]@{SourceFile=$sourceId;SourceSheet=$sheetActual;SourceRow='';ReasonCode='HEADER_NOT_FOUND';DetectedPlugin='';DetectedDateTime='';DetectedComputer='';RowHash=(Get-RowHash $sourceId 0 '' '' '')});continue}
|
||||
$headerText=(($header.Row.Cells.Keys|Sort-Object|ForEach-Object { Get-Cell $header.Row $_ }) -join ';')
|
||||
foreach($row in $worksheet.Rows | Where-Object Number -gt $header.Row.Number) {
|
||||
$plugin=(Get-Cell $row $header.PluginColumn).Trim(); $dateText=(Get-Cell $row $header.DateColumn).Trim(); $timeText=if($header.TimeColumn){(Get-Cell $row $header.TimeColumn).Trim()}else{''}; $computer=if($header.ComputerColumn){(Get-Cell $row $header.ComputerColumn).Trim()}else{''}; $dateInfo=$row.Cells[$header.DateColumn].Date
|
||||
if(!$plugin -and !$dateText -and !$computer){continue}
|
||||
$rawRowsExamined++
|
||||
$reason=''; if(!$plugin){$reason='PLUGIN_NOT_FOUND'} elseif(!$dateText){$reason='DATE_NOT_FOUND'} elseif($null -eq $dateInfo){$reason='INVALID_DATE'} elseif(!$computer){$reason='COMPUTER_NOT_FOUND'}
|
||||
if($reason){$rejected.Add([pscustomobject]@{SourceFile=$sourceId;SourceSheet=$sheetActual;SourceRow=$row.Number;ReasonCode=$reason;DetectedPlugin=$plugin;DetectedDateTime=($dateText+' '+$timeText).Trim();DetectedComputer=$computer;RowHash=(Get-RowHash $sourceId $row.Number $plugin $dateText $computer)});continue}
|
||||
$date=$dateInfo.Date; if($timeText){$timeInfo=Get-DateValue $timeText $false 0 $dates;if($null -ne $timeInfo){$date=$date.Date.Add($timeInfo.Date.TimeOfDay)}}
|
||||
$eventsRaw.Add([pscustomobject]@{PluginName=$plugin;PluginNameNormalized=(Normalize-Plugin $plugin);LaunchDateTime=$date.ToString('yyyy-MM-ddTHH:mm:ss');LaunchDate=$date.ToString('yyyy-MM-dd');LaunchMonth=$date.ToString('yyyy-MM');ComputerName=$computer;ComputerNameNormalized=(Normalize-Computer $computer);SourceFile=$sourceId;SourceSheet=$sheetActual;SourceRow=$row.Number;ParseRule=if($dateInfo.Rule -eq 'DATE_ONLY'){'DATE_ONLY'}else{'DATE_TIME'} })
|
||||
}
|
||||
$result='PARSED'
|
||||
} finally { $zip.Dispose() }
|
||||
} catch { $rejected.Add([pscustomobject]@{SourceFile=$sourceId;SourceSheet=$sheetActual;SourceRow='';ReasonCode='READ_ERROR';DetectedPlugin='';DetectedDateTime='';DetectedComputer='';RowHash=(Get-RowHash $sourceId 0 '' '' '')}) }
|
||||
$rejectedCount=$rejected.Count-$rejectedBefore; if($file.Length -ne $beforeSize -or $file.LastWriteTimeUtc -ne $beforeTime -or (Get-Sha256 $file.FullName) -ne $hash){throw "Source modified: $sourceId"}
|
||||
$inventory.Add([pscustomobject]@{SourceFile=$sourceId;HasPlant3DSheet=$plant;ActualSheetName=$sheetActual;RowCount=$rowCount;ColumnCount=$columnCount;Headers=$headerText;SHA256=$hash;ParseResult=$result;RejectedRows=$rejectedCount})
|
||||
}
|
||||
|
||||
$grouped = $eventsRaw | Group-Object { if($_.ParseRule -eq 'DATE_ONLY'){"$($_.PluginNameNormalized)|$($_.LaunchDateTime)|$($_.ComputerNameNormalized)|$($_.SourceFile)|$($_.SourceRow)"}else{"$($_.PluginNameNormalized)|$($_.LaunchDateTime)|$($_.ComputerNameNormalized)"} } | Sort-Object Name
|
||||
$events=[Collections.Generic.List[object]]::new(); foreach($group in $grouped){$item=$group.Group|Sort-Object SourceFile,SourceRow|Select -First 1;$events.Add([pscustomobject]@{EventId=('EVT-{0:D6}' -f ($events.Count+1));PluginName=$item.PluginName;PluginNameNormalized=$item.PluginNameNormalized;LaunchDateTime=$item.LaunchDateTime;LaunchDate=$item.LaunchDate;LaunchMonth=$item.LaunchMonth;ComputerName=$item.ComputerName;ComputerNameNormalized=$item.ComputerNameNormalized;SourceFile=$item.SourceFile;SourceSheet=$item.SourceSheet;SourceRow=$item.SourceRow;ParseRule=$item.ParseRule;DuplicateCount=$group.Count})}
|
||||
$events=@($events|Sort-Object PluginNameNormalized,LaunchDateTime,ComputerNameNormalized,SourceFile,SourceRow)
|
||||
|
||||
$pluginSummary=[Collections.Generic.List[object]]::new(); foreach($group in ($events|Group-Object PluginNameNormalized)){ $g=@($group.Group); $pc=$g|Group-Object ComputerNameNormalized|Sort-Object Count -Descending|Select-Object -First 1; $pluginSummary.Add([pscustomobject]@{PluginName=$g[0].PluginName;PluginNameNormalized=$group.Name;TotalLaunches=$g.Count;ComputerCount=($g.ComputerNameNormalized|Sort-Object -Unique).Count;FirstLaunch=($g.LaunchDateTime|Sort-Object|Select-Object -First 1);LastLaunch=($g.LaunchDateTime|Sort-Object|Select-Object -Last 1);ActiveDays=($g.LaunchDate|Sort-Object -Unique).Count;ActiveMonths=($g.LaunchMonth|Sort-Object -Unique).Count;MostActiveComputer=$pc.Name;MostActiveComputerLaunches=$pc.Count;ShareOfAllLaunches=if($events.Count){[math]::Round($g.Count/$events.Count,6)}else{0}}) }; $pluginSummary=@($pluginSummary|Sort-Object PluginName|Sort-Object TotalLaunches -Descending)
|
||||
$pcSummary=[Collections.Generic.List[object]]::new(); foreach($group in ($events|Group-Object ComputerNameNormalized)){ $g=@($group.Group); $plugin=$g|Group-Object PluginNameNormalized|Sort-Object Count -Descending|Select-Object -First 1; $pcSummary.Add([pscustomobject]@{ComputerName=$g[0].ComputerName;ComputerNameNormalized=$group.Name;TotalLaunches=$g.Count;UniquePlugins=($g.PluginNameNormalized|Sort-Object -Unique).Count;FirstLaunch=($g.LaunchDateTime|Sort-Object|Select-Object -First 1);LastLaunch=($g.LaunchDateTime|Sort-Object|Select-Object -Last 1);ActiveDays=($g.LaunchDate|Sort-Object -Unique).Count;MostUsedPlugin=$plugin.Name;MostUsedPluginLaunches=$plugin.Count}) }; $pcSummary=@($pcSummary|Sort-Object ComputerNameNormalized)
|
||||
$months=@($events.LaunchMonth|Sort -Unique); $plugins=@($events|Group PluginNameNormalized|Sort Name); $pluginPc=@(); foreach($p in $plugins){$r=[ordered]@{Plugin=$p.Group[0].PluginName;TotalLaunches=$p.Count;Computers=($p.Group.ComputerNameNormalized|Sort -Unique).Count;FirstLaunch=($p.Group.LaunchDateTime|Sort|Select -First 1);LastLaunch=($p.Group.LaunchDateTime|Sort|Select -Last 1)};foreach($pc in @($events.ComputerNameNormalized|Sort -Unique)){$r[$pc]=(@($p.Group|? ComputerNameNormalized -eq $pc)).Count};$pluginPc+=[pscustomobject]$r}
|
||||
$monthRows=@();foreach($p in $plugins){$r=[ordered]@{Plugin=$p.Group[0].PluginName};foreach($m in $months){$r[$m]=(@($p.Group|? LaunchMonth -eq $m)).Count};$monthRows+=[pscustomobject]$r}
|
||||
$eventView=@($events|%{[pscustomobject]@{Плагин=$_.PluginName;'Дата и время запуска'=$_.LaunchDateTime;Компьютер=$_.ComputerName;'Исходный XLSX'=$_.SourceFile;'Исходная строка'=$_.SourceRow}})
|
||||
|
||||
Csv $events (Join-Path $OutputDirectory 'plugin-usage-events.csv'); Csv $pluginSummary (Join-Path $OutputDirectory 'plugin-summary.csv'); Csv $pcSummary (Join-Path $OutputDirectory 'pc-summary.csv'); Csv $pluginPc (Join-Path $OutputDirectory 'plugin-pc-matrix.csv'); Csv $monthRows (Join-Path $OutputDirectory 'plugin-month-matrix.csv'); Csv $rejected (Join-Path $OutputDirectory 'rejected-records.csv'); Csv $inventory (Join-Path $OutputDirectory 'source-inventory.csv')
|
||||
$summaryObj=[pscustomobject]@{XlsxFilesFound=$files.Count;TemporaryXlsxIgnored=$temporaryIgnored;FilesWithPlant3DSheet=($inventory|? HasPlant3DSheet).Count;FilesWithoutPlant3DSheet=($inventory|? {-not $_.HasPlant3DSheet}).Count;FilesParsed=($inventory|? ParseResult -eq 'PARSED').Count;FilesFailed=($inventory|? ParseResult -eq 'FAILED').Count;RawRows=$rawRowsExamined;ValidRows=$eventsRaw.Count;UniqueEvents=$events.Count;Duplicates=(($events|Measure DuplicateCount -Sum).Sum-$events.Count);RejectedRows=$rejected.Count;DateRange=if($events.Count){"$($events[0].LaunchDate) .. $($events[-1].LaunchDate)"}else{''};UniquePlugins=($events.PluginNameNormalized|Sort -Unique).Count;UniqueComputers=($events.ComputerNameNormalized|Sort -Unique).Count;MostUsedPlugin=if($pluginSummary.Count){$pluginSummary[0].PluginName}else{''};MostActiveComputer=if($pcSummary.Count){$pcSummary[0].ComputerName}else{''};SourceModified='NO'}
|
||||
[IO.File]::WriteAllText((Join-Path $OutputDirectory 'summary.json'),($summaryObj|ConvertTo-Json -Depth 4),$utf8)
|
||||
|
||||
function XmlEscape([string]$Value){if($null -eq $Value){return ''};return [Security.SecurityElement]::Escape($Value)}
|
||||
function ExcelColumn([int]$N){$s='';while($N -gt 0){$N--; $s=([char](65+($N%26)))+$s;$N=[math]::Floor($N/26)};return $s}
|
||||
function SheetXml([object[]]$Rows){$sb=[Text.StringBuilder]::new();[void]$sb.Append('<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><sheetData>');$r=1;foreach($row in $Rows){[void]$sb.Append(('<row r="'+$r+'">'));$c=1;foreach($prop in $row.PSObject.Properties){$v=XmlEscape ([string]$prop.Value);$ref=(ExcelColumn $c)+$r;[void]$sb.Append(('<c r="'+$ref+'" t="inlineStr"><is><t xml:space="preserve">'+$v+'</t></is></c>'));$c++};[void]$sb.Append('</row>');$r++};[void]$sb.Append('</sheetData></worksheet>');return $sb.ToString()}
|
||||
function Build-Workbook([string]$Path,[System.Collections.IDictionary]$Sheets){
|
||||
$fs=[IO.File]::Create($Path); $zip=[IO.Compression.ZipArchive]::new($fs,[IO.Compression.ZipArchiveMode]::Create)
|
||||
try {
|
||||
$types='<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/><Default Extension="xml" ContentType="application/xml"/><Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>'
|
||||
for($i=1;$i -le $Sheets.Count;$i++){$types+=('<Override PartName="/xl/worksheets/sheet'+$i+'.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>')}; $types+='</Types>'
|
||||
$root='<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/></Relationships>'
|
||||
$work='<?xml version="1.0" encoding="UTF-8" standalone="yes"?><workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"><sheets>'
|
||||
$rels='<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">'
|
||||
$i=1; foreach($name in $Sheets.Keys){$work+=('<sheet name="'+(XmlEscape $name)+'" sheetId="'+$i+'" r:id="rId'+$i+'"/>');$rels+=('<Relationship Id="rId'+$i+'" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet'+$i+'.xml"/>');$i++}; $work+='</sheets></workbook>'; $rels+='</Relationships>'
|
||||
$entries=[ordered]@{'[Content_Types].xml'=$types;'_rels/.rels'=$root;'xl/workbook.xml'=$work;'xl/_rels/workbook.xml.rels'=$rels}; $i=1; foreach($name in $Sheets.Keys){$entries[('xl/worksheets/sheet'+$i+'.xml')]=SheetXml $Sheets[$name];$i++}
|
||||
foreach($item in $entries.GetEnumerator()){$entry=$zip.CreateEntry($item.Key);$entry.LastWriteTime=[DateTimeOffset]::new(2000,1,1,0,0,0,[TimeSpan]::Zero);$writer=[IO.StreamWriter]::new($entry.Open(),$utf8);try{$writer.Write($item.Value)}finally{$writer.Dispose()}}
|
||||
} finally {$zip.Dispose();$fs.Dispose()}
|
||||
}
|
||||
$summaryRows=@([pscustomobject]@{Плагин='Плагин';'Количество запусков'='Количество запусков';'Количество компьютеров'='Количество компьютеров';'Первый запуск'='Первый запуск';'Последний запуск'='Последний запуск';'Активных дней'='Активных дней';'Активных месяцев'='Активных месяцев';'Самый активный компьютер'='Самый активный компьютер';'Запусков на самом активном компьютере'='Запусков на самом активном компьютере';'Доля всех запусков'='Доля всех запусков'})+@($pluginSummary|%{[pscustomobject]@{Плагин=$_.PluginName;'Количество запусков'=$_.TotalLaunches;'Количество компьютеров'=$_.ComputerCount;'Первый запуск'=$_.FirstLaunch;'Последний запуск'=$_.LastLaunch;'Активных дней'=$_.ActiveDays;'Активных месяцев'=$_.ActiveMonths;'Самый активный компьютер'=$_.MostActiveComputer;'Запусков на самом активном компьютере'=$_.MostActiveComputerLaunches;'Доля всех запусков'=$_.ShareOfAllLaunches}})
|
||||
$pluginPcHeader=[ordered]@{Plugin='Плагин';TotalLaunches='Всего запусков';Computers='Компьютеров';FirstLaunch='Первый запуск';LastLaunch='Последний запуск'}; foreach($pc in @($events.ComputerNameNormalized|Sort-Object -Unique)){$pluginPcHeader[$pc]=$pc}; $pluginPcRows=@([pscustomobject]$pluginPcHeader)+@($pluginPc)
|
||||
$pcRows=@([pscustomobject]@{Компьютер='Компьютер';'Всего запусков'='Всего запусков';'Уникальных плагинов'='Уникальных плагинов';'Первый запуск'='Первый запуск';'Последний запуск'='Последний запуск';'Активных дней'='Активных дней';'Самый используемый плагин'='Самый используемый плагин';'Количество его запусков'='Количество его запусков'})+@($pcSummary|%{[pscustomobject]@{Компьютер=$_.ComputerName;'Всего запусков'=$_.TotalLaunches;'Уникальных плагинов'=$_.UniquePlugins;'Первый запуск'=$_.FirstLaunch;'Последний запуск'=$_.LastLaunch;'Активных дней'=$_.ActiveDays;'Самый используемый плагин'=$_.MostUsedPlugin;'Количество его запусков'=$_.MostUsedPluginLaunches}})
|
||||
$monthRowsFinal=@([pscustomobject]@{Плагин='Плагин'})+@($monthRows); $eventRowsFinal=@([pscustomobject]@{Плагин='Плагин';'Дата и время запуска'='Дата и время запуска';Компьютер='Компьютер';'Исходный XLSX'='Исходный XLSX';'Исходная строка'='Исходная строка'})+@($eventView)
|
||||
$finalSheets=[ordered]@{'Итог'=$summaryRows;'Плагин × ПК'=$pluginPcRows;'По компьютерам'=$pcRows;'По месяцам'=$monthRowsFinal;'События'=$eventRowsFinal}
|
||||
Build-Workbook (Join-Path $OutputDirectory 'plugin-usage-final.xlsx') $finalSheets
|
||||
|
||||
$topPlugins=if($pluginSummary.Count){($pluginSummary|Select -First 20|%{"- $($_.PluginName): $($_.TotalLaunches)"}) -join "`n"}else{'- нет валидных событий'}
|
||||
$topComputers=if($pcSummary.Count){($pcSummary|Select -First 20|%{"- $($_.ComputerName): $($_.TotalLaunches)"}) -join "`n"}else{'- нет валидных событий'}
|
||||
$readme=@"
|
||||
# Plant3D usage from XLSX
|
||||
|
||||
Source is read-only. Only Plant3D sheets are analyzed; other sheets are ignored.
|
||||
|
||||
XLSX files: $($summaryObj.XlsxFilesFound)
|
||||
Temporary XLSX ignored: $($summaryObj.TemporaryXlsxIgnored)
|
||||
Files with Plant3D: $($summaryObj.FilesWithPlant3DSheet)
|
||||
Files without Plant3D: $($summaryObj.FilesWithoutPlant3DSheet)
|
||||
Files parsed: $($summaryObj.FilesParsed)
|
||||
Files failed: $($summaryObj.FilesFailed)
|
||||
Candidate rows examined: $($summaryObj.RawRows)
|
||||
Unique events: $($summaryObj.UniqueEvents)
|
||||
Duplicates: $($summaryObj.Duplicates)
|
||||
Rejected rows: $($summaryObj.RejectedRows)
|
||||
Date range: $($summaryObj.DateRange)
|
||||
Unique plugins: $($summaryObj.UniquePlugins)
|
||||
Unique computers: $($summaryObj.UniqueComputers)
|
||||
Most used plugin: $($summaryObj.MostUsedPlugin)
|
||||
Most active computer: $($summaryObj.MostActiveComputer)
|
||||
Source modified: NO
|
||||
|
||||
The Plant3D tables contain plugin and date fields but no computer-name column. The user field was not substituted for computer and was not published. Rows without a computer are rejected with COMPUTER_NOT_FOUND.
|
||||
|
||||
Top plugins:
|
||||
$topPlugins
|
||||
|
||||
Top computers:
|
||||
$topComputers
|
||||
|
||||
Repeat:
|
||||
./tools/plugin-usage/Build-Plant3DExcelUsageMatrix.ps1 -SourceRoot C:/dev/TEMP/CheckPlugin -SheetName Plant3D -OutputDirectory ./migration/audits/plugin-usage-plant3d-xlsx-20260731
|
||||
|
||||
SourceFile values are anonymized as source-0001.xlsx. Project numbers, names, users and paths are not stored.
|
||||
"@
|
||||
$readme=[regex]::Replace($readme,'(?m)[ \t]+$','')
|
||||
[IO.File]::WriteAllText((Join-Path $OutputDirectory 'README.md'),$readme,$utf8)
|
||||
Reference in New Issue
Block a user