├── git_pull.cmd ├── new_base ├── 1Cv8.1CD.cfl ├── 1Cv8.1CL.cfl ├── 1Cv8.cgr.cfl ├── 1Cv8tmp.1CD.cfl ├── 1Cv8tmp.1CL.cfl ├── 1Cv8.1CD ├── readme.txt └── 1Cv8Log │ └── 1Cv8.lgd ├── Block8 ├── .gitignore ├── packman.txt ├── homework01.png ├── deploy_distr.os ├── package.edf └── Jenkinsfile ├── src ├── xUnitFor1C │ └── ШаблонЮнитТеста │ │ ├── maps.txt │ │ ├── und │ │ ├── version │ │ ├── root │ │ ├── 50175b89-f91c-4516-a824-5670ebd59a88.0 │ │ │ └── info │ │ ├── copyinfo │ │ ├── versions │ │ └── 04e22986-c4dc-4556-baf2-57d27e27a8c6 │ │ ├── renames.txt │ │ └── ObjectModule.bsl └── ReadXLSX │ └── ЧтениеXLSXбезВК │ ├── und │ ├── version │ ├── root │ ├── 18528942-b13d-4756-a1e1-a7951fb20d18 │ ├── copyinfo │ ├── versions │ ├── e34edc1e-ee15-4f6a-9929-5bc6fab32406 │ └── 18528942-b13d-4756-a1e1-a7951fb20d18.0 │ ├── maps.txt │ ├── renames.txt │ └── Form │ └── Форма │ └── Форма.bsl ├── Block9 ├── cyclo.cmd ├── copy_paste_det.cmd ├── runner help.txt ├── syntax-check.cmd ├── readme.txt ├── cyclo.os └── Cyclo_KrapivinAndrey.os ├── Block4 ├── gitsync_run.cmd └── block4.txt ├── commit.cmd ├── Block6 ├── pickles.cmd ├── start_vb.cmd ├── homework │ ├── allure report.png │ ├── pickles report.png │ ├── VBParams.json │ └── Jenkinsfile ├── allure.groovy └── readme.txt ├── Block_final └── readme.txt ├── безопасность.txt ├── ссылки.txt ├── Block2 ├── gitlab.txt ├── 01_postgres_5433.png ├── 02_postgres_5434.png ├── gmail_smtp_settings_for_gitlab.txt ├── postgres.txt └── docker-compose.yml ├── Block3 └── jenkins.txt ├── README.md ├── securities_micex.md ├── Block7 ├── hometask.txt └── run_xunit.cmd ├── windows firewall.txt ├── .gitmodules ├── ReadXLSX └── ЧтениеXLSXбезВК.epf ├── Examples ├── infostart_165807.docx ├── ТЗ на права доступа.docx ├── ГОСТ 34.602-89 пример.docx ├── TechDoc_example_P2ClientGate.doc ├── К-3-15 Техническое задание СЭД.pdf ├── programmist1c.ru │ └── TZ-na-vnedrenie-UPP.doc ├── ПроектДоработкиУТ11_холодные_звонки.docx └── ПроектДоработкиУТ11_холодные_звонки.txt ├── deployka_new_feature_base.cmd ├── xUnitFor1C └── ШаблонЮнитТеста.epf ├── Logos ├── ВключениеОтключениеЛогирования.epf ├── levels.bsl ├── use_logos.bsl └── CreateLogSettings.bsl ├── securities_micex ├── ListingSecurityList111.csv └── csv.os ├── вопросы.txt ├── Playlist.ini ├── что запускать для работы.txt ├── regexp ├── поиск объявления функции │ ├── module2.bsl │ ├── module.bsl │ ├── trasser.os │ ├── t2.os │ └── lookback.os └── regexp1C.bsl └── Block5 ├── Jenkinsfile └── readme.txt /git_pull.cmd: -------------------------------------------------------------------------------- 1 | git pull -------------------------------------------------------------------------------- /new_base/1Cv8.1CD.cfl: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /new_base/1Cv8.1CL.cfl: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /new_base/1Cv8.cgr.cfl: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /new_base/1Cv8tmp.1CD.cfl: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /new_base/1Cv8tmp.1CL.cfl: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Block8/.gitignore: -------------------------------------------------------------------------------- 1 | out/ 2 | .packman -------------------------------------------------------------------------------- /src/xUnitFor1C/ШаблонЮнитТеста/maps.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Block9/cyclo.cmd: -------------------------------------------------------------------------------- 1 | oscript ./tools/cyclo.os src out/cyclo.txt -------------------------------------------------------------------------------- /Block9/copy_paste_det.cmd: -------------------------------------------------------------------------------- 1 | cpd -d src -i *.bsl -r pmd -f cpd.xml -------------------------------------------------------------------------------- /src/ReadXLSX/ЧтениеXLSXбезВК/und/version: -------------------------------------------------------------------------------- 1 | { 2 | {216,0} 3 | } -------------------------------------------------------------------------------- /src/xUnitFor1C/ШаблонЮнитТеста/und/version: -------------------------------------------------------------------------------- 1 | { 2 | {216,0} 3 | } -------------------------------------------------------------------------------- /Block4/gitsync_run.cmd: -------------------------------------------------------------------------------- 1 | gitsync export e:\workspace\storage_trade ./src/cf -------------------------------------------------------------------------------- /commit.cmd: -------------------------------------------------------------------------------- 1 | git add . 2 | git commit -m "update" 3 | git push origin master -------------------------------------------------------------------------------- /src/ReadXLSX/ЧтениеXLSXбезВК/und/root: -------------------------------------------------------------------------------- 1 | {2,e34edc1e-ee15-4f6a-9929-5bc6fab32406,} -------------------------------------------------------------------------------- /Block6/pickles.cmd: -------------------------------------------------------------------------------- 1 | pickles -f features -o out/pickles -l ru --df dhtml --sn "Trade" -------------------------------------------------------------------------------- /src/xUnitFor1C/ШаблонЮнитТеста/und/root: -------------------------------------------------------------------------------- 1 | {2,04e22986-c4dc-4556-baf2-57d27e27a8c6,} -------------------------------------------------------------------------------- /Block_final/readme.txt: -------------------------------------------------------------------------------- 1 | https://vt-tech.eu/articles/programming/265-gitlab-jenkins-v2.html -------------------------------------------------------------------------------- /src/xUnitFor1C/ШаблонЮнитТеста/und/50175b89-f91c-4516-a824-5670ebd59a88.0/info: -------------------------------------------------------------------------------- 1 | {3,1,0,"",0} -------------------------------------------------------------------------------- /безопасность.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/latestalexey/Course_CI_CD/HEAD/безопасность.txt -------------------------------------------------------------------------------- /ссылки.txt: -------------------------------------------------------------------------------- 1 | сообщество по автоматизированному тестированию 2 | http://automated-testing.info/ -------------------------------------------------------------------------------- /Block2/gitlab.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/latestalexey/Course_CI_CD/HEAD/Block2/gitlab.txt -------------------------------------------------------------------------------- /Block3/jenkins.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/latestalexey/Course_CI_CD/HEAD/Block3/jenkins.txt -------------------------------------------------------------------------------- /Block4/block4.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/latestalexey/Course_CI_CD/HEAD/Block4/block4.txt -------------------------------------------------------------------------------- /Block8/packman.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/latestalexey/Course_CI_CD/HEAD/Block8/packman.txt -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Course_CI_CD 2 | Курс CI-CD от Silverbulleters. Заметки. Настройки. Полезности. 3 | -------------------------------------------------------------------------------- /new_base/1Cv8.1CD: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/latestalexey/Course_CI_CD/HEAD/new_base/1Cv8.1CD -------------------------------------------------------------------------------- /securities_micex.md: -------------------------------------------------------------------------------- 1 | список торгуемых ценных бумаг можно взять здесь 2 | http://www.moex.com/a1600 -------------------------------------------------------------------------------- /src/xUnitFor1C/ШаблонЮнитТеста/und/copyinfo: -------------------------------------------------------------------------------- 1 | {4, 2 | {0}, 3 | {0}, 4 | {0}, 5 | {0,0}, 6 | {0} 7 | } -------------------------------------------------------------------------------- /Block6/start_vb.cmd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/latestalexey/Course_CI_CD/HEAD/Block6/start_vb.cmd -------------------------------------------------------------------------------- /Block7/hometask.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/latestalexey/Course_CI_CD/HEAD/Block7/hometask.txt -------------------------------------------------------------------------------- /Block8/homework01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/latestalexey/Course_CI_CD/HEAD/Block8/homework01.png -------------------------------------------------------------------------------- /new_base/readme.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/latestalexey/Course_CI_CD/HEAD/new_base/readme.txt -------------------------------------------------------------------------------- /windows firewall.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/latestalexey/Course_CI_CD/HEAD/windows firewall.txt -------------------------------------------------------------------------------- /Block9/runner help.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/latestalexey/Course_CI_CD/HEAD/Block9/runner help.txt -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "template1c"] 2 | path = template1c 3 | url = https://github.com/Kirill/template1c 4 | -------------------------------------------------------------------------------- /new_base/1Cv8Log/1Cv8.lgd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/latestalexey/Course_CI_CD/HEAD/new_base/1Cv8Log/1Cv8.lgd -------------------------------------------------------------------------------- /src/ReadXLSX/ЧтениеXLSXбезВК/maps.txt: -------------------------------------------------------------------------------- 1 | Form\Форма\Форма.bsl-->18528942-b13d-4756-a1e1-a7951fb20d18.0 (52, 803) 2 | -------------------------------------------------------------------------------- /Block2/01_postgres_5433.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/latestalexey/Course_CI_CD/HEAD/Block2/01_postgres_5433.png -------------------------------------------------------------------------------- /Block2/02_postgres_5434.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/latestalexey/Course_CI_CD/HEAD/Block2/02_postgres_5434.png -------------------------------------------------------------------------------- /ReadXLSX/ЧтениеXLSXбезВК.epf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/latestalexey/Course_CI_CD/HEAD/ReadXLSX/ЧтениеXLSXбезВК.epf -------------------------------------------------------------------------------- /Examples/infostart_165807.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/latestalexey/Course_CI_CD/HEAD/Examples/infostart_165807.docx -------------------------------------------------------------------------------- /deployka_new_feature_base.cmd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/latestalexey/Course_CI_CD/HEAD/deployka_new_feature_base.cmd -------------------------------------------------------------------------------- /xUnitFor1C/ШаблонЮнитТеста.epf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/latestalexey/Course_CI_CD/HEAD/xUnitFor1C/ШаблонЮнитТеста.epf -------------------------------------------------------------------------------- /Block6/homework/allure report.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/latestalexey/Course_CI_CD/HEAD/Block6/homework/allure report.png -------------------------------------------------------------------------------- /Examples/ТЗ на права доступа.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/latestalexey/Course_CI_CD/HEAD/Examples/ТЗ на права доступа.docx -------------------------------------------------------------------------------- /Block6/homework/pickles report.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/latestalexey/Course_CI_CD/HEAD/Block6/homework/pickles report.png -------------------------------------------------------------------------------- /Examples/ГОСТ 34.602-89 пример.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/latestalexey/Course_CI_CD/HEAD/Examples/ГОСТ 34.602-89 пример.docx -------------------------------------------------------------------------------- /Block2/gmail_smtp_settings_for_gitlab.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/latestalexey/Course_CI_CD/HEAD/Block2/gmail_smtp_settings_for_gitlab.txt -------------------------------------------------------------------------------- /Examples/TechDoc_example_P2ClientGate.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/latestalexey/Course_CI_CD/HEAD/Examples/TechDoc_example_P2ClientGate.doc -------------------------------------------------------------------------------- /Logos/ВключениеОтключениеЛогирования.epf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/latestalexey/Course_CI_CD/HEAD/Logos/ВключениеОтключениеЛогирования.epf -------------------------------------------------------------------------------- /Examples/К-3-15 Техническое задание СЭД.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/latestalexey/Course_CI_CD/HEAD/Examples/К-3-15 Техническое задание СЭД.pdf -------------------------------------------------------------------------------- /securities_micex/ListingSecurityList111.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/latestalexey/Course_CI_CD/HEAD/securities_micex/ListingSecurityList111.csv -------------------------------------------------------------------------------- /Block9/syntax-check.cmd: -------------------------------------------------------------------------------- 1 | runner syntax-check --junitpath syntaxcheck.xml --groupbymetadata --ibconnection "/Slocalhost:2541\trade_test" --mode -ThinClient -Server -------------------------------------------------------------------------------- /Examples/programmist1c.ru/TZ-na-vnedrenie-UPP.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/latestalexey/Course_CI_CD/HEAD/Examples/programmist1c.ru/TZ-na-vnedrenie-UPP.doc -------------------------------------------------------------------------------- /Examples/ПроектДоработкиУТ11_холодные_звонки.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/latestalexey/Course_CI_CD/HEAD/Examples/ПроектДоработкиУТ11_холодные_звонки.docx -------------------------------------------------------------------------------- /вопросы.txt: -------------------------------------------------------------------------------- 1 | постоянно падает контейнер с дженкинсом. как посмотреть логи? 2 | 3 | пересоздается контейнер гитлаб. он запускается через compose. почему пересоздается? -------------------------------------------------------------------------------- /src/ReadXLSX/ЧтениеXLSXбезВК/und/18528942-b13d-4756-a1e1-a7951fb20d18: -------------------------------------------------------------------------------- 1 | {1, 2 | {1, 3 | {0, 4 | {9, 5 | {0, 6 | {0,0,18528942-b13d-4756-a1e1-a7951fb20d18},"Форма", 7 | {1,"ru","Форма"},""},0,1}, 8 | {0} 9 | } 10 | },0} -------------------------------------------------------------------------------- /Block7/run_xunit.cmd: -------------------------------------------------------------------------------- 1 | chcp 65001 2 | vrunner xunit e:\workspace\git\trade\tools\xUnitFor1C\Tests\Smoke\ --pathxunit e:\workspace\git\trade\tools\xUnitFor1C\xddTestRunner.epf --reportsxunit "ГенераторОтчетаJUnitXML{out/junit.xml}" --xddExitCodePath ./out/junitstatus.log --ibconnection "/Slocalhost:2541\trade_test" --xddConfig ./tools/xunitparams.json -------------------------------------------------------------------------------- /Block8/deploy_distr.os: -------------------------------------------------------------------------------- 1 | // используем деплойку для разворачивания конфигурации из шаблона 2 | 3 | ЗапуститьПриложение("deployka loadcfg /Fe:\workspace\trade1944fromTemplate\ d:\1C\1cv8\tmplts\SBCourse\trade19400\1.0.1.1\ /mode -load",,Истина); 4 | ЗапуститьПриложение("deployka dbupdate /Fe:\workspace\trade1944fromTemplate\ -allow-warnings",,Истина); -------------------------------------------------------------------------------- /src/xUnitFor1C/ШаблонЮнитТеста/renames.txt: -------------------------------------------------------------------------------- 1 | 04e22986-c4dc-4556-baf2-57d27e27a8c6-->und\04e22986-c4dc-4556-baf2-57d27e27a8c6 2 | 50175b89-f91c-4516-a824-5670ebd59a88.0\info-->und\50175b89-f91c-4516-a824-5670ebd59a88.0\info 3 | 50175b89-f91c-4516-a824-5670ebd59a88.0\text-->ObjectModule.bsl 4 | copyinfo-->und\copyinfo 5 | root-->und\root 6 | version-->und\version 7 | versions-->und\versions 8 | -------------------------------------------------------------------------------- /src/ReadXLSX/ЧтениеXLSXбезВК/renames.txt: -------------------------------------------------------------------------------- 1 | 18528942-b13d-4756-a1e1-a7951fb20d18-->und\18528942-b13d-4756-a1e1-a7951fb20d18 2 | 18528942-b13d-4756-a1e1-a7951fb20d18.0-->und\18528942-b13d-4756-a1e1-a7951fb20d18.0 3 | copyinfo-->und\copyinfo 4 | e34edc1e-ee15-4f6a-9929-5bc6fab32406-->und\e34edc1e-ee15-4f6a-9929-5bc6fab32406 5 | root-->und\root 6 | version-->und\version 7 | versions-->und\versions 8 | -------------------------------------------------------------------------------- /src/xUnitFor1C/ШаблонЮнитТеста/und/versions: -------------------------------------------------------------------------------- 1 | {1,7,"",0d244ec8-b2c3-4b4e-a405-b2a1ed366104,"versions",510e17d0-f9cf-49ea-bf49-b716c45ae536,"root",177ca169-a5e8-47f4-bc04-83f62aaf68ae,"50175b89-f91c-4516-a824-5670ebd59a88.0",9df57e3f-c942-45a3-b1ba-9433742e279a,"version",050d7b8a-d538-4081-afcf-742105a316c2,"04e22986-c4dc-4556-baf2-57d27e27a8c6",8617be35-7005-40ea-845d-e55c80b50850,"copyinfo",fd3336a2-73c0-405f-b212-e192256ce604} -------------------------------------------------------------------------------- /Logos/levels.bsl: -------------------------------------------------------------------------------- 1 | УровниЛога = Новый Структура; 2 | УровниЛога.Вставить("Отладка" , 0); 3 | УровниЛога.Вставить("Информация" , 1); 4 | УровниЛога.Вставить("Предупреждение" , 2); 5 | УровниЛога.Вставить("Ошибка" , 3); 6 | УровниЛога.Вставить("КритичнаяОшибка", 4); 7 | УровниЛога.Вставить("Отключить" , 5); 8 | 9 | 1 0 1 2 3 4 5 10 | "DEFAULT,DEBUG,INFO,WARN,ERROR,CRITICALERROR,DISABLE,"; -------------------------------------------------------------------------------- /Block6/allure.groovy: -------------------------------------------------------------------------------- 1 | import jenkins.* 2 | import jenkins.model.* 3 | import hudson.* 4 | import hudson.model.* 5 | 6 | System.setProperty("hudson.model.DirectoryBrowserSupport.CSP", "sandbox; default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';") 7 | System.setProperty("jenkins.model.DirectoryBrowserSupport.CSP", "sandbox; default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';") -------------------------------------------------------------------------------- /src/ReadXLSX/ЧтениеXLSXбезВК/und/copyinfo: -------------------------------------------------------------------------------- 1 | {4, 2 | {2, 3 | {18528942-b13d-4756-a1e1-a7951fb20d18,18528942-b13d-4756-a1e1-a7951fb20d18,1, 4 | {d5b0e5ed-256d-401c-9c36-f630cafd8a62,"Форма"} 5 | }, 6 | {3d102e8d-f24e-451d-90d7-9e11b0e139cb,3d102e8d-f24e-451d-90d7-9e11b0e139cb,1, 7 | {c3831ec8-d8d5-4f93-8a22-f9bfae07327f,"ВнешняяОбработка1"} 8 | } 9 | }, 10 | {1, 11 | {312233da-5e39-45fa-b3d8-e88d1041a136,3d102e8d-f24e-451d-90d7-9e11b0e139cb,0} 12 | }, 13 | {0}, 14 | {0,0}, 15 | {0} 16 | } -------------------------------------------------------------------------------- /src/ReadXLSX/ЧтениеXLSXбезВК/und/versions: -------------------------------------------------------------------------------- 1 | {1,8,"",7c9ba625-3b3c-43c9-bb1b-e5fdd2d460b0,"versions",870178f4-d1fa-4fc1-8428-13742079b75a,"e34edc1e-ee15-4f6a-9929-5bc6fab32406",ded5110c-1c4d-4318-8615-e0e831705cbf,"root",89db8ff5-1f97-4a4a-8e9f-63025d0d30c7,"18528942-b13d-4756-a1e1-a7951fb20d18.0",292c7438-2218-469f-a6d0-246818e9fc36,"version",8da6f53e-3d59-46ec-baa2-7bdc28f0a469,"18528942-b13d-4756-a1e1-a7951fb20d18",2f631172-9459-490e-b0d6-bcb32e9ce5c8,"copyinfo",ae2b2f8b-7556-4c17-a075-a0a97c4caae0} -------------------------------------------------------------------------------- /Playlist.ini: -------------------------------------------------------------------------------- 1 | [Settings] 2 | Activation=http://uvsoftium.ru/courses/activate/432 3 | Sound= 4 | Subtitles= 5 | Volume=911 6 | Speed=x1.0 7 | HTMLScale=0 8 | Key=99b3ba1c2bd0cc0964f6c5c8f3d3d623509193640BtUk6GNd8JrqDbI03hmE1pPlbr5SloeH7jBvr0EgW66htjWZp4j1XxNgiquR81GhPa/83akvRbr8+BaHXQE6hq48icXntHe37Xg0X2io0YA05OMOqRMdKm09ES4N8hZMHL6ajQME5n9X5YAOV/LHJ/SYZz4oiRAo+zAiF3cRpTitgDQTxwovSRSYwASxL6ilBjwJg5BoEnA8+WKO+5GZBfHewhEbrIZGvPSIxTVFCtz8eEZHtkDgGDPzTzDznUwvk01nzWhnNRAReZRwx4MrnjjoWgpXCYXICr4WwIOUfLrCDYiGWnJri8nMQElyxkDuGjxhMITbV4WHG3d5uWmesgEmiaWug+6Yw== 9 | -------------------------------------------------------------------------------- /Examples/ПроектДоработкиУТ11_холодные_звонки.txt: -------------------------------------------------------------------------------- 1 | https://infostart.ru/project/697634/ 2 | 3 | О проекте 4 | 5 | Реализовать в 1С УТ11 работу с холодными звонками по базе контрагентов. 6 | Техническое задание во вложении прилагается. 7 | Подобное задание не одно и на них отводится порядка 6 месяцев. 8 | Оплата ежемесячная, обговаривается индивидуально, от 40 до 65 тыс.руб. 9 | Присылайте свои резюме c пометкой 1С проект. 10 | 11 | От вас нужен опыт разработки на управляемых формах и желание работать удаленно и полный день за фиксированную сумму в месяц 12 | Команды разработчиков просьба не беспокоить. -------------------------------------------------------------------------------- /src/xUnitFor1C/ШаблонЮнитТеста/und/04e22986-c4dc-4556-baf2-57d27e27a8c6: -------------------------------------------------------------------------------- 1 | {1, 2 | {04e22986-c4dc-4556-baf2-57d27e27a8c6},1, 3 | {c3831ec8-d8d5-4f93-8a22-f9bfae07327f, 4 | {1, 5 | {4,71cd0303-7b56-47e9-a5d0-60049402b1f2,6ec4ca90-b06f-49e7-8810-18d0c33e4a7b, 6 | {0, 7 | {0, 8 | {0,0,50175b89-f91c-4516-a824-5670ebd59a88},"ШаблонЮнитТеста", 9 | {1,"ru","Шаблон юнит-теста"},""} 10 | },00000000-0000-0000-0000-000000000000,"",00000000-0000-0000-0000-000000000000},4, 11 | {2bcef0d1-0981-11d6-b9b8-0050bae0a95d,0}, 12 | {3daea016-69b7-4ed4-9453-127911372fe6,0}, 13 | {d5b0e5ed-256d-401c-9c36-f630cafd8a62,0}, 14 | {ec6bb5e5-b7a8-4d75-bec9-658107a699cf,0} 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /Block6/homework/VBParams.json: -------------------------------------------------------------------------------- 1 | { 2 | "ВыполнитьСценарии": true, 3 | "ЗавершитьРаботуСистемы": true, 4 | "ЗакрытьTestClentПослеЗапускаСценариев": true, 5 | "КаталогФич": "$workspaceRoot/features", 6 | "КаталогиБиблиотек": [ 7 | "./features/Libraries" 8 | ], 9 | "ДелатьОтчетВФорматеАллюр": true, 10 | "КаталогOutputAllureБазовый": "$workspaceRoot/out/allure", 11 | "ВыгружатьСтатусВыполненияСценариевВФайл": true, 12 | "ПутьКФайлуДляВыгрузкиСтатусаВыполненияСценариев": "$workspaceRoot/out/buildStatus.log", 13 | "ДелатьОтчетВФорматеCucumberJson": true, 14 | "КаталогOutputCucumberJson": "$workspaceRoot/out/cucumber" 15 | } -------------------------------------------------------------------------------- /src/ReadXLSX/ЧтениеXLSXбезВК/und/e34edc1e-ee15-4f6a-9929-5bc6fab32406: -------------------------------------------------------------------------------- 1 | {1, 2 | {e34edc1e-ee15-4f6a-9929-5bc6fab32406},1, 3 | {c3831ec8-d8d5-4f93-8a22-f9bfae07327f, 4 | {1, 5 | {4,312233da-5e39-45fa-b3d8-e88d1041a136,23c24883-f511-4b1b-8d20-7fcfa3d8118d, 6 | {0, 7 | {0, 8 | {0,0,3d102e8d-f24e-451d-90d7-9e11b0e139cb},"ВнешняяОбработка1", 9 | {0},""} 10 | },18528942-b13d-4756-a1e1-a7951fb20d18,"",00000000-0000-0000-0000-000000000000},4, 11 | {2bcef0d1-0981-11d6-b9b8-0050bae0a95d,0}, 12 | {3daea016-69b7-4ed4-9453-127911372fe6,0}, 13 | {d5b0e5ed-256d-401c-9c36-f630cafd8a62,1,18528942-b13d-4756-a1e1-a7951fb20d18}, 14 | {ec6bb5e5-b7a8-4d75-bec9-658107a699cf,0} 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /что запускать для работы.txt: -------------------------------------------------------------------------------- 1 | postgres windows (обычная версия, без патчей для 1С) 2 | стартует автоматом как сервис 3 | port:5432 4 | 5 | postgres 1C (9.6.5) 6 | стартует автоматом как сервис 7 | port:5434 8 | 9 | 10 | gitlab. ищем его по адресу localhost:10080 11 | 12 | зайти в каталог e:\workspace\gitlab\ и через cmd выполнить 13 | 14 | docker-compose up -d 15 | 16 | jenkins. ищем его по адресу localhost:8080 17 | 18 | главная нода 19 | e:\workspace\jenkins\start.cmd 20 | 21 | slave node 22 | e:\workspace\jenkins_slave\start.cmd 23 | (останется окно cmd) 24 | 25 | 26 | 27 | В ходе выполнения работы были установлены 28 | Сервер 1С 8.3.10.2639 29 | Сервер RAS этой же версии 30 | Postgres двух версий -------------------------------------------------------------------------------- /Logos/use_logos.bsl: -------------------------------------------------------------------------------- 1 | НастройкиЛогирования = Обработки.НастройкиЛогированияЛог.Создать(); 2 | Если НастройкиЛогирования.ПрочитатьИзКонфигурации("ИмпортОтчетаБрокераОткрытие") = Неопределено Тогда 3 | НастройкиЛогирования.ЗаписатьВКонфигурацию("ИмпортОтчетаБрокераОткрытие", НастройкиЛогирования.УровниЛога.Отладка, СоздатьНастройкуЛога()); 4 | КонецЕсли; 5 | 6 | МенеджерЛогирования = Обработки.МенеджерЛогированияЛог.Создать(); 7 | Лог = МенеджерЛогирования.ПолучитьЛог("ИмпортОтчетаБрокераОткрытие"); 8 | 9 | Лог.Информация("Начали загрузку данных из файла <%1>", ИмяФайла); 10 | 11 | ... 12 | 13 | Лог.Информация("Закончили загрузку данных из файла <%1>", ИмяФайла); 14 | Лог.Закрыть(); 15 | Лог = Неопределено; 16 | 17 | -------------------------------------------------------------------------------- /Logos/CreateLogSettings.bsl: -------------------------------------------------------------------------------- 1 | Функция СоздатьНастройкуЛога() Экспорт 2 | 3 | ПутьККаталогуЛогирования = "e:\workspace\MicexTrader\DEV_Area\"; 4 | мФайлы = НайтиФайлы(ПутьККаталогуЛогирования); 5 | Если мФайлы.Количество() = 0 Тогда 6 | ПутьККаталогуЛогирования = КаталогВременныхФайлов(); 7 | КонецЕсли; 8 | Возврат "DEBUG, openbrokerfile, console 9 | | 10 | |appender.openbrokerfile=ВыводЛогаВФайл 11 | |appender.openbrokerfile.file="+ПутьККаталогуЛогирования+"openbrokerfile.log 12 | |appender.openbrokerfile.logName=ИмпортОтчетаБрокераОткрытие 13 | | 14 | |appender.console=ВыводЛогаВКонсоль 15 | |appender.console.logName=ИмпортОтчетаБрокераОткрытие"; 16 | 17 | //TODO можно еще вывод в ЖР добавить в appender 18 | 19 | КонецФункции 20 | -------------------------------------------------------------------------------- /Block8/package.edf: -------------------------------------------------------------------------------- 1 | {1, 2 | { 3 | {1,2, 4 | {"en","infostart19400"}, 5 | {"ru","infostart19400"} 6 | }, 7 | {1,2, 8 | {"en","Конфигурация"}, 9 | {"ru","Конфигурация"} 10 | }, 11 | {#base64:} 12 | }, 13 | {1, 14 | {1,0,"Конфигурация","infostart19400","%ВерсияМетаданных%","SBCourse\trade19400\%НомерСборки%", 15 | { 16 | {"/", 17 | {1, 18 | {a81674e9-32f0-4ea6-aeae-799e6ab4a48b,"1Cv8.cf - Файл конфигурации",1,00000000-0000-0000-0000-000000000000,"SBCourse\trade19400","",124fa494-1559-4495-b896-3f2415d3474c,"1Cv8.cf",1,0,0,1} 19 | }, 20 | {0}, 21 | {0} 22 | } 23 | } 24 | } 25 | }, 26 | {1,124fa494-1559-4495-b896-3f2415d3474c,"CheckoutDir",0,"V8BuildRoot"}, 27 | {1,"Полный",0, 28 | {0},00000000-0000-0000-0000-000000000000,"",00000000-0000-0000-0000-000000000000,""}, 29 | {0} 30 | } -------------------------------------------------------------------------------- /regexp/поиск объявления функции/module2.bsl: -------------------------------------------------------------------------------- 1 | //модуль для тестирования трассировщика. 2 | //в измененном модуле трассировщик должен добавить вызовы логирования 3 | 4 | Функция ВыполнитьТрассировкуМодуля( ИсходныйТекст, 5 | Параметр8, 6 | Параметр9, 7 | Параметр1) Экспорт 8 | 9 | а = НайтиФайлы(); 10 | Для Каждого Эл из а Цикл 11 | КонецЦикла; 12 | 13 | КонецФункции 14 | 15 | Функция НайтиЗначениеВыражения( ИсходныйТекст, 16 | Параметр8, 17 | Параметр9, 18 | Параметр1) 19 | 20 | а = НайтиФайлы(); 21 | Для Каждого Эл из а Цикл 22 | КонецЦикла; 23 | 24 | КонецФункции 25 | 26 | Функция 27 | ВыполнитьТрассировкуМодуля 28 | ( 29 | ИсходныйТекст, 30 | Параметр8, 31 | Параметр9, 32 | Параметр1 33 | ) 34 | Экспорт 35 | 36 | f = 1; 37 | Сообщить(12); 38 | КонецФункции -------------------------------------------------------------------------------- /regexp/поиск объявления функции/module.bsl: -------------------------------------------------------------------------------- 1 | //модуль для тестирования трассировщика. 2 | //в измененном модуле трассировщик должен добавить вызовы логирования 3 | 4 | Процедура Старт(Параметр1 = 0, Парамет2 = 9) 5 | 6 | КонецПроцедуры 7 | 8 | Функция Вызов1(Параметр3) 9 | 10 | Сообщить(Параметр3); 11 | 12 | КонецФункции 13 | 14 | Функция Вызов2(Параметр4, Параметр5) 15 | 16 | КонецФункции 17 | 18 | Процедура Вызов3(Параметр6, Параметр7 = 78) 19 | 20 | КонецПроцедуры 21 | 22 | Procedure Вызов3(Параметр6, Параметр7 = 78) 23 | 24 | EndProcedure 25 | 26 | Функция СкопироватьФайлы(Источник, Приемник) 27 | 28 | КонецФункции 29 | 30 | Функция ВыполнитьТрассировкуМодуля( ИсходныйТекст, 31 | Параметр8, 32 | Параметр9, 33 | Параметр1) Экспорт 34 | 35 | КонецФункции 36 | 37 | Функция СкопироватьФайлы 38 | (Источник, Приемник) 39 | 40 | КонецФункции -------------------------------------------------------------------------------- /Block2/postgres.txt: -------------------------------------------------------------------------------- 1 | Установленные версии на 2017-11-05 2 | 3 | postgres 9.6.5 4 | версия без патчей для 1С 5 | на нем будет держать базы gitlab 6 | установлен в 7 | C:\Program Files\PostgreSQL\9.6\ 8 | данные и конфиги здесь 9 | E:\PostgreSQL\9.6\data 10 | user: postgres 11 | pass: postgres 12 | port:5432 13 | 14 | postgres 9.6.5 1С 15 | Установлен сюда 16 | C:\Program Files\PostgresPro 1C\9.6 17 | данные и конфиги тут 18 | E:\PostgresPro1C\9.6\data 19 | user: postgres 20 | pass: postgres 21 | port:5434 22 | 23 | 24 | 25 | Как запустить 2 версии PostgreSQL на одной машине? 26 | https://forum.infostart.ru/forum86/topic59286/ 27 | При установке двух и более экземпляров PostgreSQL на одном компьютере (сервере), при создании или добавлении базы, адрес сервера базы данных (строку соединения) нужно указывать в формате: ip-адрес пробел порт 28 | При подключении (создании) на компьютере с PostgreSQL: localhost port=5433 или 127.0.0.1 port=5433 29 | При подключении (создании) на компьютере в локальной сети: "ip-адрес сервера пробел port=порт" экземпляра PostgreSQL (192.168.0.2 port=5434) 30 | p.s. посмотреть на каком порту висит экземпляр PostgreSQL можно в pgAdmin (пример на скриншоте) 31 | 32 | 33 | Если меняем порт postgres, используемого для gitlab, то это надо делать в двух местах 34 | 1 файл ...\data\postgres.conf 35 | 2 файл e:\workspace\gitlab\docker-compose.yml - для запуска гитлаба 36 | НО! на текущий момент это не работает, т.к. гитлаб перестает запускаться, если порт не 5432 37 | Задал вопрос на форуме xdd -------------------------------------------------------------------------------- /Block5/Jenkinsfile: -------------------------------------------------------------------------------- 1 | connectionString = "" /*define it without def to make it global. https://stackoverflow.com/questions/45514585/exception-while-executing-groovy-script-from-jenkinsfile-groovy-lang-missingprop*/ 2 | def uccode 3 | def lockParams 4 | 5 | def versionText 6 | def versionValue 7 | 8 | pipeline { 9 | agent { 10 | label 'bdd' 11 | } 12 | environment { 13 | Storage = credentials('Storage_Trade_CiBot') 14 | /* логин и пароль разделенные двоеточием:*/ 15 | /* Storage - login:pass*/ 16 | /* Storage_Usr - логин*/ 17 | /* Storage_Psw - пароль*/ 18 | } 19 | 20 | stages { 21 | stage ('Обновление тестового контура'){ 22 | steps { 23 | timestamps { 24 | script { 25 | connectionString = "\"/S${env.Server1C}\\${env.Database1C}\"" 26 | uccode = "\"123\"" 27 | lockParams = "-lockmessage \"base is blocked\" -lockuccode ${uccode}" 28 | 29 | versionText = readFile encoding: 'UTF-8', file: 'src/cf/VERSION' 30 | versionValue = (versionText =~ /(.*)<\/VERSION>/)[0][1] 31 | } 32 | 33 | cmd("oscript --version") 34 | cmd("deployka session lock -ras ${env.ServerRAS} -db ${env.Database1C} ${lockParams}") 35 | cmd("deployka session kill -ras ${env.ServerRAS} -db ${env.Database1C} ${lockParams}") 36 | cmd("deployka loadrepo ${connectionString} \"${env.StoragePath}\" -storage-user ${env.Storage_Usr} -storage-pwd ${env.Storage_Psw} -uccode \"123\" -storage-ver ${versionValue}") 37 | cmd("deployka dbupdate ${connectionString} -allow-warnings -uccode \"123\"") 38 | cmd("deployka session unlock -ras ${env.ServerRAS} -db ${env.Database1C}") 39 | } 40 | } 41 | } 42 | } 43 | } 44 | def cmd(command) { 45 | if (isUnix()) { 46 | sh "${command}" 47 | } else { 48 | bat "chcp 65001\n${command}" 49 | } 50 | } -------------------------------------------------------------------------------- /Block6/readme.txt: -------------------------------------------------------------------------------- 1 | # Block 6 2 | 3 | каталог с фичей берем из блока 4 4 | 5 | установили vanessa-runner: 6 | opm install vanessa-runner 7 | 8 | написали файл настроек для runner - tools\VBParams.json 9 | 10 | в репозиторий торговли добавили сабмодуль vanessa-behavior: 11 | (запускать из каталога e:\workspace\git\trade\) 12 | git submodule add https://github.com/silverbulleters/vanessa-behavior tools/vanessa-behavior 13 | чтобы запускать по относительному пути 14 | 15 | команда запуска runner - в файле start_vb.cmd 16 | 17 | 18 | установили precommit1c в репозиторий торговли, как сабмодуль. 19 | 20 | Подключаем Allure к Jenkins 21 | 22 | 23 | Файл allure.groovy надо поместить по адресу e:\workspace\volumes\jenkins\init.groovy.d\ 24 | Этим мы разрешим дженкинсу выполнять скрипты, чтобы работала ссылка HTML-Report на странице задачи. 25 | (требуется рестарт контейнера с Jenkins) 26 | Строки в этом файле переносить нельзя! Иначе получим ошибку 27 | 28 | WARNING: Failed to run script file:/var/jenkins_home/init.groovy.d/allure.groovy 29 | org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed: 30 | /var/jenkins_home/init.groovy.d/allure.groovy: 7: expecting anything but ''\n''; got it anyway @ line 7, column 50. 31 | irectoryBrowserSupport.CSP", " 32 | ^ 33 | 2017-11-11T09:30:59.782508600Z 34 | 1 error 35 | 2017-11-11T09:30:59.782513600Z 36 | 37 | Cucumber reports 38 | 39 | Аллюр не позволяет анализироват успешность выполнения сценариев во времени. 40 | Накопление статистики по выполнению сценариев предоставляет плагин cucumber reports 41 | vanessa-behavior умеет предоставлять информацию в формате этого плагина 42 | 43 | Его нужно вызывать через специальный шаг сборочной линии - step 44 | 45 | синтаксис вызова шага: step([$class: 'GitHubSetCommitStatusBuilder']) 46 | 47 | Заходим в pipeline syntax 48 | В поле Sample step выбираем step: Generate build step 49 | В поле Build step выбираем Cucumber reports 50 | Нажимаем Generate pipeline script 51 | Получаем результат, как в строке ниже. 52 | cucumber fileIncludePattern: '**/*.json', sortingMethod: 'ALPHABETICAL' 53 | 54 | ## Публикация результатов cucumber reports в сборочной линии 55 | 56 | в jenkinsfile добавили 57 | step([ 58 | $class: 'CucumberReportPublisher', 59 | fileIncludePattern: '*.json', 60 | jsonReportDirectory: 'out/cucumber' 61 | ]) 62 | 63 | ## Подключение Pickes 64 | 65 | генерация живой документации. 66 | 67 | Установка напрямую на slave-агент 68 | 69 | идем на 70 | https://github.com/picklesdoc/pickles 71 | 72 | Еще нужно установить плагин Cucumber Living Documentation 73 | -------------------------------------------------------------------------------- /regexp/поиск объявления функции/trasser.os: -------------------------------------------------------------------------------- 1 | //Проходит по всему тексту модуля и добавляет сразу после объявления функции код записи события в лог. 2 | //В событии пишется факт вызова данной процедуры. 3 | 4 | //Порядок работы. 5 | //1 выгрузить модули, сложить их в каталог по иерархии 6 | //2 в трассировщике задать путь к этому корневому каталогу в переменной КорневойПуть 7 | 8 | 9 | //TODO пока сделано простым циклом обхода файлов. надо ли делать иерархическое дерево каталогов? 10 | 11 | Перем КорневойПуть; 12 | 13 | 14 | 15 | Функция СкопироватьФайлы 16 | (Источник, Приемник) 17 | 18 | КонецФункции 19 | 20 | 21 | Функция ВывестиГруппыРегВыражения(Совпадение) 22 | сообщить(" группы:"); 23 | Для каждого Группа Из Совпадение.Группы Цикл 24 | Сообщить("--------------"); 25 | сообщить("значение " + Совпадение.Значение); 26 | сообщить("индекс " + Совпадение.Индекс); 27 | сообщить("длина " + Совпадение.Длина); 28 | 29 | КонецЦикла; 30 | КонецФункции 31 | 32 | Функция ДобавитьТрассировкуВФайл(ПолноеИмяФайла) 33 | 34 | т = Новый ТекстовыйДокумент; 35 | т.Прочитать(ПолноеИмяФайла, КодировкаТекста.UTF8); 36 | тт = т.получитьТекст(); 37 | 38 | паттерн = ""; 39 | 40 | //описание паттерна 41 | //слово "функция" 42 | //затем пробел (любое количество) или перенос строки (любое количество) 43 | //затем имяФункции - строка и/или символ подчеркивания 44 | //затем пробел или перенос строки (любок кол-во) 45 | //затем ( 46 | //затем параметры 47 | //затем 48 | паттерн = "Функция(\s|\n)*[A-Za-z0-9А-Яа-я_]*(\s|\n)*\((.|\n)*\)\s+(Экспорт)?(\s|;){1}"; 49 | //паттерн = "Функция .*\(([A-Za-z0-9А-Яа-я_=,]|\n)*\)\s+(Экспорт)+"; 50 | 51 | 52 | РегЭксп = Новый Regex(паттерн); 53 | 54 | РегЭксп.IgnoreCase = Истина; 55 | РегЭксп.Multiline = Истина; 56 | 57 | Совпадения = РегЭксп.НайтиСовпадения(тт); 58 | 59 | 60 | Сообщить("Всего совпадений "+Совпадения.Количество() ); 61 | Сообщить("----------------------------------"); 62 | 63 | Для каждого Совпадение Из Совпадения Цикл 64 | сообщить("значение " + Совпадение.Значение); 65 | сообщить("индекс " + Совпадение.Индекс); 66 | сообщить("длина " + Совпадение.Длина); 67 | 68 | //ВывестиГруппыРегВыражения(Совпадение); 69 | 70 | Сообщить("----------------------------------"); 71 | 72 | КонецЦикла; 73 | 74 | //Для Счетчик = 1 По т.КоличествоСтрок Цикл 75 | // текСтр = т.ПолучитьСтроку(Счетчик); 76 | // Если Найти(текСтр, "процедура (") 77 | //КонецЦикла; 78 | 79 | КонецФункции 80 | 81 | 82 | КорневойПуть = "c:\1C\PROJECTS\Трассировка_кода_1С\"; 83 | 84 | Сообщить("||||||||||||||||||||||||||||||||||||||||||"); 85 | 86 | мФайлы = НайтиФайлы(КорневойПуть, "module2.bsl", Истина); 87 | 88 | Для каждого ф Из мФайлы Цикл 89 | 90 | //Сообщить(1); 91 | 92 | Если ф.ЭтоКаталог() Тогда 93 | Продолжить; 94 | КонецЕсли; 95 | 96 | 97 | ДобавитьТрассировкуВФайл(ф.ПолноеИмя); 98 | 99 | КонецЦикла; -------------------------------------------------------------------------------- /regexp/поиск объявления функции/t2.os: -------------------------------------------------------------------------------- 1 | //тест шаблона рег выражения. это самостоятельный тест, ему не нужны другие файлы 2 | 3 | //http://www.script-coding.com/WSH/RegExp.html 4 | // * Определяет ни одного или несколько символов, стоящих перед ним. Эквивалентно {0,}. 5 | // + Определяет один или несколько символов, стоящих перед ним. Эквивалентно {1,}. 6 | // ? Определяет ни одного или один символ, стоящий перед ним. Эквивалентно {0,1}. 7 | // Если этот метасимвол идёт непосредственно за конструкциями (*, +, ?, {n}, {n,}, {n,m}), это приводит к некоторому изменению алгоритма поиска по заданному шаблону, что проиллюстрировано примером ниже. 8 | 9 | Сообщить("||||||||||||||||||||||||||||||||||||||||||"); 10 | 11 | 12 | СтрокаГдеИщем = " Функция 13 | | Тест( пар2 = ""!@#$%^&*()_+=-=123456asdfждлрЛОР789?.,\|\:;'|/|\|-2_$"" 14 | | , а 15 | | ) Экспорт ; а=1; 16 | | сообщить(1); 17 | |КонецФункции 18 | |"; 19 | 20 | к = Символ(34); //кавычка 21 | 22 | мПаттерн = Новый Массив; 23 | 24 | мПаттерн.Добавить("Функция"); 25 | мПаттерн.Добавить("(\s|\n)+");//Пробел или перенос строки. один или более 26 | мПаттерн.Добавить("[A-Za-zА-Яа-я0-9_]+");//имя функции 27 | мПаттерн.Добавить("(\s|\n)*");//Пробел или перенос строки. ноль или более 28 | мПаттерн.Добавить("\(");//скобка 29 | 30 | //блок описания параметра. одного. 31 | мПаттерн.Добавить("(\s|\n)*");//Пробел или перенос строки. ноль или более 32 | мПаттерн.Добавить("[A-Za-zА-Яа-я0-9_]+");//имя параметра 33 | мПаттерн.Добавить("(\s|\n)*");//Пробел или перенос строки. ноль или более 34 | мПаттерн.Добавить("=?");//знак "равно". 0 или 1 35 | мПаттерн.Добавить("(\s|\n)*");//Пробел или перенос строки. ноль или более 36 | мПаттерн.Добавить(".+");//значение параметра. любой символ до пробела/переноса/запятой 37 | мПаттерн.Добавить("(\s|\n)*");//Пробел или перенос строки. ноль или более 38 | //как быть с запятой? 39 | мПаттерн.Добавить(",?");//запятая. 0 или 1 40 | мПаттерн.Добавить("(\s|\n)*");//Пробел или перенос строки. ноль или более 41 | //конец блока описания параметра 42 | 43 | //как написать поиск повторения блока параметра? 44 | 45 | мПаттерн.Добавить("(\s|\n)*");//Пробел или перенос строки. ноль или более 46 | мПаттерн.Добавить("\)");//скобка 47 | мПаттерн.Добавить("(\s|\n)*");//Пробел или перенос строки. ноль или более 48 | мПаттерн.Добавить("(Экспорт)?");//слово Экспорт. ноль или 1 49 | мПаттерн.Добавить("(\s|\n)*");//Пробел или перенос строки. ноль или более 50 | мПаттерн.Добавить(";?"); //ноль или один 51 | мПаттерн.Добавить("(\s|\n)*");//Пробел или перенос строки. ноль или более 52 | 53 | паттерн = ""; 54 | Для сч=0 По мПаттерн.Количество()-1 Цикл 55 | паттерн = паттерн + мПаттерн[сч]; 56 | КонецЦикла; 57 | сообщить(паттерн); 58 | РегЭксп = Новый Regex(паттерн); 59 | 60 | РегЭксп.IgnoreCase = Истина; 61 | РегЭксп.Multiline = Истина; 62 | 63 | Совпадения = РегЭксп.НайтиСовпадения(СтрокаГдеИщем); 64 | 65 | Сообщить("Всего совпадений "+Совпадения.Количество() ); 66 | Сообщить("----------------------------------"); 67 | 68 | Для каждого Совпадение Из Совпадения Цикл 69 | сообщить("значение " + Совпадение.Значение); 70 | сообщить("индекс " + Совпадение.Индекс); 71 | сообщить("длина " + Совпадение.Длина); 72 | 73 | //ВывестиГруппыРегВыражения(Совпадение); 74 | 75 | Сообщить("----------------------------------"); 76 | 77 | КонецЦикла; 78 | 79 | 80 | -------------------------------------------------------------------------------- /src/xUnitFor1C/ШаблонЮнитТеста/ObjectModule.bsl: -------------------------------------------------------------------------------- 1 | Перем КонтекстЯдра; 2 | Перем БазовыеУтверждения; //БазовыеУтверждения 3 | Перем Ожидаем; //УтвержденияBDD 4 | 5 | //Перем ВременныеФайлы; //ВременныеФайлы 6 | //Перем ГенераторОтчетаJUnitXML;//ГенераторОтчетаJUnitXML 7 | //Перем ГенераторОтчетаMXL;//ГенераторОтчетаMXL 8 | //Перем ЗагрузчикИзПодсистемКонфигурации;//ЗагрузчикИзПодсистемКонфигурации 9 | //Перем ЗагрузчикКаталога;//ЗагрузчикКаталога 10 | //Перем ЗагрузчикФайла;//ЗагрузчикФайла 11 | //Перем ЗапросыИзБД;//ЗапросыИзБД 12 | //Перем КомандныйФайл;//КомандныйФайл 13 | //Перем ПарсерКоманднойСтроки;//ПарсерКоманднойСтроки 14 | //Перем ПостроительДереваТестов;//ПостроительДереваТестов 15 | //Перем СериализаторMXL;//СериализаторMXL 16 | //Перем СтроковыеУтилиты;//СтроковыеУтилиты 17 | //Перем УтвержденияПроверкаТаблиц;//УтвержденияПроверкаТаблиц 18 | 19 | Процедура Инициализация(КонтекстЯдраПараметр) Экспорт 20 | КонтекстЯдра = КонтекстЯдраПараметр; 21 | БазовыеУтверждения = КонтекстЯдра.Плагин("БазовыеУтверждения"); 22 | Ожидаем = КонтекстЯдра.Плагин("УтвержденияBDD"); 23 | 24 | //ВременныеФайлы = КонтекстЯдра.Плагин("ВременныеФайлы"); 25 | //ГенераторОтчетаJUnitXML = КонтекстЯдра.Плагин("ГенераторОтчетаJUnitXML"); 26 | //ГенераторОтчетаMXL = КонтекстЯдра.Плагин("ГенераторОтчетаMXL"); 27 | //ЗагрузчикИзПодсистемКонфигурации = КонтекстЯдра.Плагин("ЗагрузчикИзПодсистемКонфигурации"); 28 | //ЗагрузчикКаталога = КонтекстЯдра.Плагин("ЗагрузчикКаталога"); 29 | //ЗагрузчикФайла = КонтекстЯдра.Плагин("ЗагрузчикФайла"); 30 | //ЗапросыИзБД = КонтекстЯдра.Плагин("ЗапросыИзБД"); 31 | //КомандныйФайл = КонтекстЯдра.Плагин("КомандныйФайл"); 32 | //ПарсерКоманднойСтроки = КонтекстЯдра.Плагин("ПарсерКоманднойСтроки"); 33 | //ПостроительДереваТестов = КонтекстЯдра.Плагин("ПостроительДереваТестов"); 34 | //СериализаторMXL = КонтекстЯдра.Плагин("СериализаторMXL"); 35 | //СтроковыеУтилиты = КонтекстЯдра.Плагин("СтроковыеУтилиты"); 36 | //УтвержденияПроверкаТаблиц = КонтекстЯдра.Плагин("УтвержденияПроверкаТаблиц"); 37 | 38 | КонецПроцедуры 39 | 40 | Процедура ЗаполнитьНаборТестов(НаборТестов) Экспорт 41 | 42 | НаборТестов.Добавить("ТестДолжен_проверить_выполняемость_функции_"); 43 | 44 | КонецПроцедуры 45 | 46 | //+----------------------------------------------------------------------- 47 | //{ Блок юнит-тестов 48 | //+----------------------------------------------------------------------- 49 | 50 | Процедура ПередЗапускомТеста() Экспорт 51 | НачатьТранзакцию(); 52 | КонецПроцедуры 53 | Процедура ПослеЗапускаТеста() Экспорт 54 | Если ТранзакцияАктивна() Тогда 55 | ОтменитьТранзакцию(); 56 | КонецЕсли; 57 | КонецПроцедуры 58 | 59 | //шаблон теста 60 | Процедура ТестДолжен_проверить_выполняемость_функции_() Экспорт 61 | 62 | __здесь_имя_общего_модуля_или_объект_обработки_ = Неопределено; 63 | 64 | //параметры метода должны передаваться через массив. пример массива ниже 65 | мПараметры = новый Массив; 66 | мПараметры.Добавить( ); 67 | мПараметры.Добавить( ); 68 | мПараметры.Добавить( ); 69 | мПараметры.Добавить( ); 70 | 71 | БазовыеУтверждения.ПроверитьМетодВыполнился(__здесь_имя_общего_модуля_или_объект_обработки_, "__сюда_пишем_имя_метода", мПараметры, ""); 72 | 73 | КонецПроцедуры 74 | -------------------------------------------------------------------------------- /regexp/regexp1C.bsl: -------------------------------------------------------------------------------- 1 | //общий модуль. Клиент-сервер 2 | 3 | // 4 | Функция Инициализация (Шаблон, ИскатьДоПервогоСовпадения = Истина, МногоСтрок = Истина, ИгнорироватьРегистр = Истина) Экспорт 5 | 6 | RegExp = Новый COMОбъект("VBScript.RegExp"); // создаем объект для работы с регулярными выражениями 7 | 8 | //Заполняем данные 9 | RegExp.MultiLine = МногоСтрок; // истина — текст многострочный, ложь — одна строка 10 | RegExp.Global = Не ИскатьДоПервогоСовпадения; // истина — поиск по всей строке, ложь — до первого совпадения 11 | RegExp.IgnoreCase = ИгнорироватьРегистр; // истина — игнорировать регистр строки при поиске 12 | RegExp.Pattern = Шаблон; // шаблон (регулярное выражение) 13 | 14 | Возврат RegExp; 15 | 16 | КонецФункции 17 | 18 | //Метод test проверяет, есть ли хоть одно совпадение в строке str. Возвращает true/false. 19 | //Работает, по сути, так же, как и проверка str.search(reg) != -1, 20 | Функция Проверка(RegExp, ПроверяемыйТекст) Экспорт 21 | 22 | Возврат RegExp.Test(ПроверяемыйТекст); 23 | 24 | КонецФункции 25 | 26 | // 27 | Функция Выполнить(RegExp, АнализируемыйТекст) Экспорт 28 | 29 | РезультатАнализаСтроки = RegExp.Execute(АнализируемыйТекст); 30 | 31 | МассивВыражений = Новый Массив; 32 | 33 | Для Каждого Выражение Из РезультатАнализаСтроки Цикл 34 | СтруктураВыражение = Новый Структура ("Начало, Длина, Значение, ПодВыражения", Выражение.FirstIndex, Выражение.Length,Выражение.Value); 35 | 36 | //Обработка подвыражений 37 | МассивПодВыражений = Новый Массив; 38 | Для Каждого ПодВыражение Из Выражение.SubMatches Цикл 39 | МассивПодВыражений.Добавить(ПодВыражение); 40 | КонецЦикла; 41 | СтруктураВыражение.ПодВыражения = МассивПодВыражений; 42 | 43 | МассивВыражений.Добавить (СтруктураВыражение); 44 | 45 | КонецЦикла; 46 | 47 | Возврат МассивВыражений; 48 | 49 | КонецФункции 50 | 51 | //str.search(reg). возвращает позицию первого совпадения или -1, если ничего не найдено. 52 | Функция Поиск(RegExp, ИскомыйТекст) Экспорт 53 | 54 | Возврат RegExp.Search(ИскомыйТекст); 55 | 56 | КонецФункции 57 | 58 | //str.match(reg) без флага g. В этом случае str.match(reg) находит только одно, первое совпадение. 59 | //Результат вызова – это массив, состоящий из этого совпадения, с дополнительными свойствами index – позиция, 60 | //на которой оно обнаружено и input – строка, в которой был поиск. 61 | //У этого массива не всегда только один элемент. 62 | Функция Совпадение(RegExp, ИскомыйТекст) Экспорт 63 | 64 | РезультатАнализаСтроки = RegExp.Execute(ИскомыйТекст); 65 | 66 | Возврат РезультатАнализаСтроки.Count>0; 67 | 68 | //МассивВыражений = Новый Массив; 69 | 70 | //Для Каждого Выражение Из РезультатАнализаСтроки Цикл 71 | // СтруктураВыражение = Новый Структура ("Начало, Длина, Значение, ПодВыражения", Выражение.FirstIndex, Выражение.Length,Выражение.Value); 72 | 73 | // //Обработка подвыражений 74 | // МассивПодВыражений = Новый Массив; 75 | // Для Каждого ПодВыражение Из Выражение.SubMatches Цикл 76 | // МассивПодВыражений.Добавить(ПодВыражение); 77 | // КонецЦикла; 78 | // СтруктураВыражение.ПодВыражения = МассивПодВыражений; 79 | 80 | // МассивВыражений.Добавить (СтруктураВыражение); 81 | 82 | //КонецЦикла; 83 | 84 | //Возврат МассивВыражений.Количество()>0; 85 | 86 | 87 | КонецФункции 88 | 89 | 90 | -------------------------------------------------------------------------------- /regexp/поиск объявления функции/lookback.os: -------------------------------------------------------------------------------- 1 | //тест шаблона рег выражения. это самостоятельный тест, ему не нужны другие файлы 2 | 3 | //http://www.script-coding.com/WSH/RegExp.html 4 | // * Определяет ни одного или несколько символов, стоящих перед ним. Эквивалентно {0,}. 5 | // + Определяет один или несколько символов, стоящих перед ним. Эквивалентно {1,}. 6 | // ? Определяет ни одного или один символ, стоящий перед ним. Эквивалентно {0,1}. 7 | // Если этот метасимвол идёт непосредственно за конструкциями (*, +, ?, {n}, {n,}, {n,m}), это приводит к некоторому изменению алгоритма поиска по заданному шаблону, что проиллюстрировано примером ниже. 8 | 9 | Сообщить("||||||||||||||||||||||||||||||||||||||||||"); 10 | 11 | 12 | СтрокаГдеИщем = " Функция 13 | | Тест( пар2 = ""!@#$%^&*_+=-=123456asdfждлрЛОР789?.,\|\:;'|/|\|-2_$"" 14 | | , 15 | | ) Экспорт ; а=1; 16 | | сообщить(1); 17 | |КонецФункции 18 | | 19 | |Функция Тест( пар2 = ""!@#$%^&*_+=-=123456asdfждлрЛОР789?.,\|\:;'|/|\|-2_$"", asdf) Экспорт 20 | |"; 21 | 22 | к = Символ(34); //кавычка 23 | 24 | мПаттерн = Новый Массив; 25 | 26 | мПаттерн.Добавить("Функция"); 27 | мПаттерн.Добавить("(\s|\n)+");//Пробел или перенос строки. один или более 28 | мПаттерн.Добавить("[A-Za-zА-Яа-я0-9_]+");//имя функции 29 | мПаттерн.Добавить("(\s|\n)*");//Пробел или перенос строки. ноль или более 30 | мПаттерн.Добавить("\(");//скобка 31 | 32 | //как написать поиск повторения блока параметра? 33 | //мПаттерн.Добавить("(?<=(\(|,|\s|\n)+)");//Утверждение. Смотрящее назад 34 | 35 | //блок описания параметра. одного. 36 | мПаттерн.Добавить("(\s|\n)*");//Пробел или перенос строки. ноль или более 37 | мПаттерн.Добавить("[A-Za-zА-Яа-я0-9_]+");//имя параметра 38 | мПаттерн.Добавить("(\s|\n)*");//Пробел или перенос строки. ноль или более 39 | мПаттерн.Добавить("=?");//знак "равно". 0 или 1 40 | мПаттерн.Добавить("(\s|\n)*");//Пробел или перенос строки. ноль или более 41 | мПаттерн.Добавить(".+");//значение параметра. любой символ до пробела/переноса/запятой 42 | мПаттерн.Добавить("(\s|\n)*");//Пробел или перенос строки. ноль или более 43 | //как быть с запятой? 44 | мПаттерн.Добавить(",?");//запятая. 0 или 1 45 | мПаттерн.Добавить("(\s|\n)*");//Пробел или перенос строки. ноль или более 46 | //конец блока описания параметра 47 | 48 | мПаттерн.Добавить("(\s|\n)*");//Пробел или перенос строки. ноль или более 49 | мПаттерн.Добавить("\)");//скобка 50 | мПаттерн.Добавить("(\s|\n)*");//Пробел или перенос строки. ноль или более 51 | мПаттерн.Добавить("(Экспорт)?");//слово Экспорт. ноль или 1 52 | мПаттерн.Добавить("(\s|\n)*");//Пробел или перенос строки. ноль или более 53 | мПаттерн.Добавить(";?"); //ноль или один 54 | мПаттерн.Добавить("(\s|\n)*");//Пробел или перенос строки. ноль или более 55 | 56 | паттерн = ""; 57 | Для сч=0 По мПаттерн.Количество()-1 Цикл 58 | паттерн = паттерн + мПаттерн[сч]; 59 | КонецЦикла; 60 | сообщить(паттерн); 61 | РегЭксп = Новый Regex(паттерн); 62 | 63 | РегЭксп.IgnoreCase = Истина; 64 | РегЭксп.Multiline = Истина; 65 | 66 | Совпадения = РегЭксп.НайтиСовпадения(СтрокаГдеИщем); 67 | 68 | Сообщить("Всего совпадений "+Совпадения.Количество() ); 69 | Сообщить("----------------------------------"); 70 | 71 | Для каждого Совпадение Из Совпадения Цикл 72 | сообщить("значение " + Совпадение.Значение); 73 | сообщить("индекс " + Совпадение.Индекс); 74 | сообщить("длина " + Совпадение.Длина); 75 | 76 | //ВывестиГруппыРегВыражения(Совпадение); 77 | 78 | Сообщить("----------------------------------"); 79 | 80 | КонецЦикла; 81 | 82 | 83 | -------------------------------------------------------------------------------- /Block5/readme.txt: -------------------------------------------------------------------------------- 1 | Надстройка над Jenkins - pipeline 2 | 3 | представление сборочного процесса, как кода 4 | все шаги пишутся в jenkinsfile на языке groovy (надстройка над java) 5 | файл хранится в репозитории продукта 6 | в jenkins создается задачи и указывается путь к этому файлу 7 | за выполнением этапов следит отдельный сервис на мастер-узле 8 | наглядная визуализация всего процесса сборки 9 | 10 | jenkinsfile кладем в репозиторий, чтобы его версия была связана с версией репозитория. 11 | репозиторий здесь: e:\workspace\git\trade\ 12 | 13 | сервер 1С установлен версии 8.3.10.2639, порты 2540, 2541, 2560-2591 14 | 15 | Создаем сервер RAS 16 | В командной строке (запущенной от администратора) пишем 17 | sc create "1C:Enterprise RAS" binpath="\"c:\Program Files (x86)\1cv8\8.3.10.2639\bin\ras.exe\" cluster --service --port=2545 localhost:2540" 18 | Должны получить: 19 | [SC] CreateService: успех 20 | Потом заходим в services.msc и запускаем службу. Также можно поменять запуск на Автоматический. 21 | Проверяем, что сервер администрирования запущен 22 | "c:\Program Files (x86)\1cv8\8.3.10.2639\bin\rac.exe" localhost:2545 cluster list 23 | Если все хорошо, то получим ответ: 24 | cluster : 435385a9-661f-4906-936a-53e44b41d0c6 25 | host : DESKTOP-5TC1CV4 26 | port : 2541 27 | name : "Локальный кластер" 28 | expiration-timeout : 0 29 | lifetime-limit : 0 30 | max-memory-size : 0 31 | max-memory-time-limit : 0 32 | security-level : 0 33 | session-fault-tolerance-level : 0 34 | load-balancing-mode : performance 35 | errors-count-threshold : 0 36 | kill-problem-processes : 0 37 | 38 | 39 | 40 | Блокировка базы 41 | deployka session lock -ras localhost:2545 -db trade_test -lockmessage "base is blocked" -lockuccode 123 42 | 43 | Ответ: 44 | ИНФОРМАЦИЯ - Получаю список кластеров 45 | ИНФОРМАЦИЯ - Получаю список баз кластера 46 | ИНФОРМАЦИЯ - Получен УИД базы 47 | ИНФОРМАЦИЯ - Сеансы запрещены 48 | 49 | Закрытие соединений 50 | deployka session kill -ras localhost:2545 -db trade_test -lockmessage "base is blocked" -lockuccode 123 51 | 52 | Отмена блокировки базы 53 | deployka session unlock -ras localhost:2545 -db trade_test -lockmessage "base is blocked" -lockuccode 123 54 | 55 | Jenkinsfile храним в репозитории конфигурации. Рядом с /src/cf/, т.к. пути строятся относительно расположения файла. 56 | 57 | В Jenkinsfile для паролей и адреса сервера будем использовать переменные среды 58 | 59 | 60 | ${env.ServerRAS} это localhost:2545 (сервер RAS) 61 | ${env.Database1C} это trade_test 62 | ${env.Server1C} это localhost:2541 (сервер 1C) 63 | ${env.StoragePath} это E:/workspace/storage_trade\ 64 | 65 | 66 | В учебном виде дается пример Jenkinsfile, который успешно компилируется дженкинсом , но у меня 67 | этот файл не захотел работать с первого раза. 68 | При сборке выдавалась ошибка 69 | 70 | Started by an SCM change 71 | Obtained Jenkinsfile from git http://10.0.75.1:10080/nikolai/trade 72 | [Pipeline] End of Pipeline 73 | groovy.lang.MissingPropertyException: No such property: connectionString for class: groovy.lang.Binding 74 | at groovy.lang.Binding.getVariable(Binding.java:63) 75 | ... 76 | 77 | подобный кейс описан здесь(1) 78 | https://stackoverflow.com/questions/45514585/exception-while-executing-groovy-script-from-jenkinsfile-groovy-lang-missingprop 79 | и здесь (2) 80 | https://stackoverflow.com/questions/39256131/no-such-property-error-for-string-in-groovy 81 | 82 | Я сделал, как в (1) и это помогло, объявил переменную без def: 83 | connectionString = "" 84 | 85 | цитата из (1): define it without def to make it global 86 | -------------------------------------------------------------------------------- /Block2/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | 3 | services: 4 | redis: 5 | restart: always 6 | image: sameersbn/redis:latest 7 | command: 8 | - --loglevel warning 9 | volumes: 10 | - e:/workspace/volumes/redis:/var/lib/redis:Z 11 | 12 | gitlab: 13 | restart: always 14 | image: sameersbn/gitlab:10.1.0 15 | depends_on: 16 | - redis 17 | ports: 18 | - "10080:80" 19 | - "10022:22" 20 | volumes: 21 | - e:/workspace/volumes/gitlab:/home/git/data:Z 22 | environment: 23 | - DEBUG=false 24 | 25 | - DB_ADAPTER=postgresql 26 | - DB_HOST=10.0.75.1 27 | - DB_PORT=5432 28 | - DB_USER=gitlab 29 | - DB_PASS=gitlab 30 | - DB_NAME=gitlab 31 | 32 | - REDIS_HOST=redis 33 | - REDIS_PORT=6379 34 | 35 | - TZ=Europe/Moscow 36 | - GITLAB_TIMEZONE=Moscow 37 | 38 | - GITLAB_HTTPS=false 39 | - SSL_SELF_SIGNED=false 40 | 41 | - GITLAB_HOST=localhost 42 | - GITLAB_PORT=10080 43 | - GITLAB_SSH_PORT=10022 44 | - GITLAB_RELATIVE_URL_ROOT= 45 | - GITLAB_SECRETS_DB_KEY_BASE=C06OOUHJ03Bf8jOYbjMAqaZffPdXDHD8O4Gly19hk62hOe7QKnwuPd6ISkvnVB0u 46 | - GITLAB_SECRETS_SECRET_KEY_BASE=sCq40Y6xO7vGIE3LCOfZ5Wz3ZovBnXBWbp5PXRR2MaRDGrU2nmzLgknAJVsZgh3s 47 | - GITLAB_SECRETS_OTP_KEY_BASE=Q9nhFQJgMWvVYysDXMALH2JpQGehsanuHMSdrFOzHy4MDQoWMlohZNf0qjzWwyYi 48 | 49 | - GITLAB_ROOT_PASSWORD= 50 | - GITLAB_ROOT_EMAIL= 51 | 52 | - GITLAB_NOTIFY_ON_BROKEN_BUILDS=true 53 | - GITLAB_NOTIFY_PUSHER=false 54 | 55 | - GITLAB_EMAIL=nicxx@yandex.ru 56 | - GITLAB_EMAIL_REPLY_TO=nicxx@yandex.ru 57 | - GITLAB_INCOMING_EMAIL_ADDRESS=nicxx@yandex.ru 58 | 59 | - GITLAB_BACKUP_SCHEDULE=daily 60 | - GITLAB_BACKUP_TIME=01:00 61 | 62 | - SMTP_ENABLED=true 63 | - SMTP_DOMAIN=gmail.mail.com 64 | - SMTP_HOST=smtp.gmail.com 65 | - SMTP_PORT=587 66 | - SMTP_USER=d1823244 67 | - SMTP_PASS=3221225472Trd! 68 | - SMTP_STARTTLS=true 69 | - SMTP_AUTHENTICATION=login 70 | 71 | - IMAP_ENABLED=false 72 | - IMAP_HOST=imap.yandex.ru 73 | - IMAP_PORT=993 74 | - IMAP_USER= 75 | - IMAP_PASS= 76 | - IMAP_SSL=true 77 | - IMAP_STARTTLS=false 78 | 79 | - OAUTH_ENABLED=false 80 | - OAUTH_AUTO_SIGN_IN_WITH_PROVIDER= 81 | - OAUTH_ALLOW_SSO= 82 | - OAUTH_BLOCK_AUTO_CREATED_USERS=true 83 | - OAUTH_AUTO_LINK_LDAP_USER=false 84 | - OAUTH_AUTO_LINK_SAML_USER=false 85 | - OAUTH_EXTERNAL_PROVIDERS= 86 | 87 | - OAUTH_CAS3_LABEL=cas3 88 | - OAUTH_CAS3_SERVER= 89 | - OAUTH_CAS3_DISABLE_SSL_VERIFICATION=false 90 | - OAUTH_CAS3_LOGIN_URL=/cas/login 91 | - OAUTH_CAS3_VALIDATE_URL=/cas/p3/serviceValidate 92 | - OAUTH_CAS3_LOGOUT_URL=/cas/logout 93 | 94 | - OAUTH_GOOGLE_API_KEY= 95 | - OAUTH_GOOGLE_APP_SECRET= 96 | - OAUTH_GOOGLE_RESTRICT_DOMAIN= 97 | 98 | - OAUTH_FACEBOOK_API_KEY= 99 | - OAUTH_FACEBOOK_APP_SECRET= 100 | 101 | - OAUTH_TWITTER_API_KEY= 102 | - OAUTH_TWITTER_APP_SECRET= 103 | 104 | - OAUTH_GITHUB_API_KEY= 105 | - OAUTH_GITHUB_APP_SECRET= 106 | - OAUTH_GITHUB_URL= 107 | - OAUTH_GITHUB_VERIFY_SSL= 108 | 109 | - OAUTH_GITLAB_API_KEY= 110 | - OAUTH_GITLAB_APP_SECRET= 111 | 112 | - OAUTH_BITBUCKET_API_KEY= 113 | - OAUTH_BITBUCKET_APP_SECRET= 114 | 115 | - OAUTH_SAML_ASSERTION_CONSUMER_SERVICE_URL= 116 | - OAUTH_SAML_IDP_CERT_FINGERPRINT= 117 | - OAUTH_SAML_IDP_SSO_TARGET_URL= 118 | - OAUTH_SAML_ISSUER= 119 | - OAUTH_SAML_LABEL="Our SAML Provider" 120 | - OAUTH_SAML_NAME_IDENTIFIER_FORMAT=urn:oasis:names:tc:SAML:2.0:nameid-format:transient 121 | - OAUTH_SAML_GROUPS_ATTRIBUTE= 122 | - OAUTH_SAML_EXTERNAL_GROUPS= 123 | - OAUTH_SAML_ATTRIBUTE_STATEMENTS_EMAIL= 124 | - OAUTH_SAML_ATTRIBUTE_STATEMENTS_NAME= 125 | - OAUTH_SAML_ATTRIBUTE_STATEMENTS_FIRST_NAME= 126 | - OAUTH_SAML_ATTRIBUTE_STATEMENTS_LAST_NAME= 127 | 128 | - OAUTH_CROWD_SERVER_URL= 129 | - OAUTH_CROWD_APP_NAME= 130 | - OAUTH_CROWD_APP_PASSWORD= 131 | 132 | - OAUTH_AUTH0_CLIENT_ID= 133 | - OAUTH_AUTH0_CLIENT_SECRET= 134 | - OAUTH_AUTH0_DOMAIN= 135 | 136 | - OAUTH_AZURE_API_KEY= 137 | - OAUTH_AZURE_API_SECRET= 138 | - OAUTH_AZURE_TENANT_ID= 139 | -------------------------------------------------------------------------------- /Block6/homework/Jenkinsfile: -------------------------------------------------------------------------------- 1 | connectionString = "" /*define it without def to make it global. https://stackoverflow.com/questions/45514585/exception-while-executing-groovy-script-from-jenkinsfile-groovy-lang-missingprop*/ 2 | def uccode 3 | def lockParams 4 | 5 | def versionText 6 | def versionValue 7 | 8 | pipeline { 9 | agent { 10 | label 'bdd' 11 | } 12 | environment { 13 | Storage = credentials('Storage_Trade_CiBot') 14 | /* логин и пароль разделенные двоеточием:*/ 15 | /* Storage - login:pass*/ 16 | /* Storage_Usr - логин*/ 17 | /* Storage_Psw - пароль*/ 18 | } 19 | 20 | stages { 21 | stage ('Обновление тестового контура'){ 22 | steps { 23 | timestamps { 24 | script { 25 | connectionString = "\"/S${env.Server1C}\\${env.Database1C}\"" 26 | uccode = "\"123\"" 27 | lockParams = "-lockmessage \"base is blocked\" -lockuccode ${uccode}" 28 | 29 | versionText = readFile encoding: 'UTF-8', file: 'src/cf/VERSION' 30 | versionValue = (versionText =~ /(.*)<\/VERSION>/)[0][1] 31 | } 32 | 33 | cmd("oscript --version") 34 | cmd("deployka session lock -ras ${env.ServerRAS} -db ${env.Database1C} ${lockParams}") 35 | cmd("deployka session kill -ras ${env.ServerRAS} -db ${env.Database1C} ${lockParams}") 36 | cmd("deployka loadrepo ${connectionString} \"${env.StoragePath}\" -storage-user ${env.Storage_Usr} -storage-pwd ${env.Storage_Psw} -uccode \"123\" -storage-ver ${versionValue}") 37 | cmd("deployka dbupdate ${connectionString} -allow-warnings -uccode \"123\"") 38 | cmd("deployka session unlock -ras ${env.ServerRAS} -db ${env.Database1C}") 39 | } 40 | } 41 | } 42 | stage ('Проверка поведения'){ 43 | steps { 44 | timestamps { 45 | cmd("vrunner vanessa --pathvanessa ./tools/vanessa-behavior/vanessa-behavior.epf --vanessasettings ./tools/VBParams.json --workspace . --ibconnection ${connectionString}") 46 | } 47 | } 48 | } 49 | stage ('Публикация результатов'){ 50 | steps { 51 | script { 52 | def allurePath = tool name: 'allure', type: 'allure' 53 | cmd("${allurePath}/bin/allure generate -o out/publishHTML/allure-report out/allure") 54 | } 55 | 56 | cmd("pickles -f features -o out/publishHTML/pickles -l ru --df dhtml --sn \"Trade\"") 57 | 58 | publishHTML target: [ 59 | allowMissing: false, 60 | alwaysLinkToLastBuild: false, 61 | keepAll: false, 62 | reportDir: 'out/publishHTML', 63 | reportFiles: 'allure-report/index.html,pickles/Index.html', 64 | reportName: 'HTML Report', 65 | reportTitles: 'Отчеты Allure and Pickles' 66 | ] 67 | step([ 68 | $class: 'CucumberReportPublisher', 69 | fileIncludePattern: '*.json', 70 | jsonReportDirectory: 'out/cucumber' 71 | ]) 72 | 73 | step([ 74 | $class: 'CukedoctorPublisher', 75 | featuresDir: 'out/cucumber', 76 | formt: 'HTML', 77 | hideFeaturesSection: false, 78 | hideScenarioKeyword: false, 79 | hideStepTime: false, 80 | hideSummary: false, 81 | hideTags: false, 82 | numbered: true, 83 | sectAnchors: true, 84 | title: 'Living Docs', 85 | toc: 'LEFT' 86 | 87 | ]) 88 | 89 | } 90 | 91 | } 92 | 93 | } 94 | } 95 | def cmd(command) { 96 | if (isUnix()) { 97 | sh "${command}" 98 | } else { 99 | bat "chcp 65001\n${command}" 100 | } 101 | } -------------------------------------------------------------------------------- /securities_micex/csv.os: -------------------------------------------------------------------------------- 1 | //ищет все строки в CSV-файла, с разделителем в виде ";" или "," (настраивается вручную в шаблоне регулярного выражения) 2 | //каждое поле - в кавычках 3 | 4 | #Использовать cmdline 5 | 6 | Перем РегЭксп; 7 | Перем Разделитель; 8 | 9 | Функция НайтиВсеСтроки(ПолноеИмяФайла) 10 | мФайлы = НайтиФайлы(ПолноеИмяФайла); 11 | //открываем исходный файл 12 | т = Новый ТекстовыйДокумент; 13 | т.Прочитать(ПолноеИмяФайла, КодировкаТекста.ANSI); 14 | тт = т.получитьТекст(); 15 | //поля таблицы (39) 16 | //DATESTAMP;INSTRUMENT_ID;LIST_SECTION;RN;SUPERTYPE;INSTRUMENT_TYPE;INSTRUMENT_CATEGORY;TRADE_CODE;ISIN;REGISTRY_NUMBER;REGISTRY_DATE;EMITENT_FULL_NAME;INN;NOMINAL;CURRENCY;ISSUE_AMOUNT;DECISION_DATE;OKSM_EDR;ONLY_EMITENT_FULL_NAME;REG_COUNTRY;QUALIFIED_INVESTOR;HAS_PROSPECTUS;IS_CONCESSION_AGREEMENT;IS_MORTGAGE_AGENT;INCLUDED_DURING_CREATION;SECURITY_HAS_DEFAULT;SECURITY_HAS_TECH_DEFAULT;INCLUDED_WITHOUT_COMPLIANCE;RETAINED_WITHOUT_COMPLIANCE;HAS_RESTRICTION_CIRCULATION;LISTING_LEVEL_HIST;OBLIGATION_PROGRAM_RN;COUPON_PERCENT;EARLY_REPAYMENT;EARLY_REDEMPTION;ISS_BOARDS;OTHER_SECURITIES;DISCLOSURE_PART_PAGE;DISCLOSURE_RF_INFO_PAGE; 17 | //пример строки 18 | //"27.11.2017 0:00:00";"5771";"Первый уровень";"1";"Акции";"Акция обыкновенная";"акции обыкновенные";"CBOM";"RU000A0JUG31";"10101978B";"18.08.1999 0:00:00";"""МОСКОВСКИЙ КРЕДИТНЫЙ БАНК"" (публичное акционерное общество)";"7734202860";"1";"Рубль";"27079709866";"11.03.2014 0:00:00";"";"";"";"";"+";"";"";"";"";"";"";"";"";"22.06.2015 Включение в Первый уровень 09.06.2014 Включение в Второй уровень 11.03.2014 Включение в Котировальный список ""В""";"";"";"";"";"РПС : Акции РЕПО c акциями Т+ Неполные лоты (акции) РЕПО с ЦК 1 день РЕПО с ЦК Адресное Т+ Акции и ДР РПС с ЦК: Акции и ДР РЕПО с ЦК 1 день (расч. в USD) РЕПО с ЦК 1 день (расч. в EUR) РЕПО с ЦК 7 дн. РЕПО с ЦК адр. (расч. в USD) РЕПО с ЦК адр.(расч. в EUR) РЕПО c акциями(расч.в USD) РЕПО с ЦК 7 дней c расчетами в долларах США РЕПО с ЦК 7 дней c расчетами в евро";"Облигация корпоративная, 41101978B, RU000A0JTF50 Облигация корпоративная, 41201978B, RU000A0JTPD7 Облигация биржевая, 4B020601978B, RU000A0JU880 Облигация биржевая, 4B020701978B, RU000A0JU8W1 Облигация биржевая, 4B020801978B, RU000A0JV3K6 Облигация биржевая, 4B020901978B, RU000A0JU898 Облигация биржевая, 4B021001978B, RU000A0JUQQ5 Облигация биржевая, 4B021101978B, RU000A0JUQR3 Облигация биржевая, 4B021201978B Облигация биржевая, 4B021301978B Облигация биржевая, 4B021401978B Облигация биржевая, 4B021501978B";"http://www.mkb.ru";"http://www.e-disclosure.ru/portal/company.aspx?id=202"; 19 | 20 | СпецСимволы = "~`'!""№,\.<>;%:\?\(\)\+@#$\^\&\/\*\-\\\{\}\[\]\|"; 21 | ВсеСимволы = "[A-Za-z0-9_]"; 22 | 23 | к = Символ(34); 24 | //ШаблонПоля = к + ".*?" + к; 25 | 26 | //ШаблонПоля = к + "[\w\s'!""№,\.<>;%:\?\(\)\+@#$\^\&\/\*\-\\\{\}\[\]\|]*?" + к; 27 | ШаблонПоля = к +"{1}"+ "[="+символ(34)+",\-+;\*:\w\s\\\.\(\)\?\/]*" + к+"{1}"; 28 | 29 | ШаблонСтроки = "^\w\W*$"; 30 | Шаблон = "^"; 31 | Для сч = 1 по 38 Цикл Шаблон = Шаблон + ШаблонПоля + Разделитель ; КонецЦикла; 32 | //последний разделитель может быть, а может и не быть 33 | //Шаблон = Шаблон + ШаблонПоля + Разделитель + "{0,1}" ; 34 | Шаблон = Шаблон + ШаблонПоля + Разделитель + "?"; 35 | //Сообщить(Шаблон); 36 | 37 | РегЭксп = Новый Regex(ШаблонСтроки); 38 | РегЭксп.IgnoreCase = Истина; 39 | РегЭксп.Multiline = Истина; 40 | 41 | РегЭкспПоля = Новый Regex("" + символ(34) + ";" + символ(34)+ "{0,1}"); 42 | РегЭкспПоля.IgnoreCase = Истина; 43 | РегЭкспПоля.Multiline = Ложь; 44 | 45 | Для сч = 2 по т.количествоСтрок() Цикл 46 | 47 | Поля = РегЭкспПоля.НайтиСовпадения(т.ПолучитьСтроку(сч)); 48 | ///Сообщить("Полей = " + Строка(Поля.Количество())); 49 | для каждого Поле из Поля цикл 50 | //Сообщить(Поле.группы.Количество()); 51 | для каждого Группа из Поле.группы цикл 52 | //Сообщить(группа.значение); 53 | КонецЦикла; 54 | КонецЦикла; 55 | 56 | мСтрок = РегЭкспПоля.Разделить(т.ПолучитьСтроку(сч)); 57 | Для сч2 = -мСтрок.Количество()+1 по 0 цикл 58 | если мСтрок[-сч2] = """;""" Тогда 59 | мСтрок.Удалить(-сч2); 60 | КонецЕсли; 61 | конецЦикла; 62 | для сч2 = 0 по мСтрок.Количество()-1 Цикл 63 | //сообщить(мСтрок[сч2]); 64 | конецЦикла; 65 | сообщить(мСтрок.Количество()); 66 | КонецЦикла; 67 | 68 | КонецФункции 69 | 70 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 71 | Сообщить("------------------------------------------------------------------"); 72 | 73 | Парсер = Новый ПарсерАргументовКоманднойСтроки(); 74 | Парсер.ДобавитьПараметр("ПутьКФайлу"); 75 | Параметры = Парсер.Разобрать(АргументыКоманднойСтроки); 76 | //Сообщить(Параметры["ПутьКФайлу"]); 77 | ИмяФайла = Параметры["ПутьКФайлу"]; 78 | 79 | Разделитель = ";"; //"," или ";" 80 | 81 | НайтиВсеСтроки(ИмяФайла); 82 | 83 | -------------------------------------------------------------------------------- /Block9/readme.txt: -------------------------------------------------------------------------------- 1 | Цикломатическая сложность. Расчет из командной строки. 2 | 3 | Для боевой базы это небыстрый процесс, т.к. в ней много кода. 4 | 5 | Используем файл cyclo.os. Рядом лежит файл Cyclo_KrapivinAndrey.os, это немного доработанная версия, в учебном курсе не используется 6 | Скачана с форума xdd.silverbulleters.org из темы Блок9 7 | 8 | Запуск. 9 | Кладем cyclo.os в папку tools, переходим обратно в папку trade и выполняем команду 10 | oscript ./tools/cyclo.os src out/cyclo.txt 11 | 12 | В файле cyclo.txt увидим результат, например: 13 | 14 | ИНФОРМАЦИЯ - Я расчётчик цикломатической сложности 15 | ИНФОРМАЦИЯ - Поиск файлов... 16 | ИНФОРМАЦИЯ - Анализ файла E:\workspace\git\trade\src\cf\CommonModules\ОбщийМодуль1\Ext\Module.bsl... 17 | ИНФОРМАЦИЯ - Анализ файла E:\workspace\git\trade\src\cf\Documents\ПриходнаяНакладная\Ext\ObjectModule.bsl... 18 | 19 | Создаем задачу в Jenkins 20 | 21 | 1. Создать новый item, тип - свободная конфигурация, имя - cyclo 22 | Эту задачу будем вызывать из сборочной линии 23 | 2. Переходим в настройки задачи 24 | ротация логов - 10 25 | включить timestamps 26 | включить получение репозитория 27 | ограничить выполнение на узлах с меткой bdd 28 | 3. Добавить шаг сборки "Выполнить команду Windows". 29 | В окне команды пишем: 30 | chcp 65001 31 | oscript ./tools/cyclo.os src cyclo.txt 32 | (каталог out здесь убрали, т.к. в сборочной версии репозитория его нет) 33 | 4. Выполняем задачу 34 | в сборочной директории появится файл cyclo.txt 35 | 36 | Включаем расчет в сборочную линию. 37 | 38 | В jenkinsfile Добавляем новый stage с названием "Статический анализ" 39 | 40 | stage ('Статический анализ'){ 41 | steps { 42 | script { 43 | if (env.BUILD_NUMBER.endsWith("0")) { //это условие ограничивает запуск задачи только сборкой, номер которой оканчивается на ноль, т.е. каждой десятой 44 | //если не использовать условие, то шаг можно объявить без обертки script 45 | build job: 'cyclo', wait: false 46 | } 47 | } 48 | } 49 | } 50 | 51 | Сейчас эта задача не будет запускаться параллельно со pipe-line. 52 | Увеличим количество параллельно выполняемых задач. 53 | Зайдем в Узлы, откроем подчиненный, затем его Настройки. 54 | В Реквизите "Количество процессов-исполнителей" укажем значение 2. 55 | Сейчас задача запустится параллельно. 56 | 57 | 58 | Дублирование кода. Расчет из командной строки. 59 | COPY-PASTE-DETECTOR 60 | 61 | Установить Node.js, стабильную версию. Проверить, что включен к установке npm. 62 | Через npm установить плагин cpd (copy-paste-detector) 63 | 64 | > npm install -g copy-paste-detector 65 | 66 | (-g означает, что установка делается глобальная) 67 | 68 | Запускаем проверку. 69 | > cpd -d src -i *.bsl -r pmd -f cpd.xml 70 | Получим ошибку, связанную с инициализацией парсера PHP. 71 | Исправить: 72 | 1. Установить php 73 | 2. Удалить парсер 74 | Пойдем по варианту 2. 75 | Узнать куда установилась утилита "cpd" 76 | > where cpd 77 | Путь к парсеру примерно такой: 78 | c:\Users\18232\AppData\Roaming\npm\node_modules\copy-paste-detector\lib\parser\ 79 | Удаляем файл php.js 80 | После работы утилита созадет файл cpd.xml (параметр -f) 81 | 82 | Создаем задачу в Jenkins 83 | 84 | Ставим плагин DRY Plug-in 85 | Пробуем установить без перезагрузки. Если какой-то плагин из зависимостей требует перезапуска, включим флажок "Перезапустить Jenkins по окончанию установки..." 86 | 87 | Создаем новую задачу, имя cpd, тип - "Со свободной конфигурацией" 88 | Ротация логов - 10 сборок 89 | Ограничить выполнение узлами с меткой bdd 90 | Включить получение исходного кода из git-репозитория. 91 | Добавить timestamps. 92 | Добавит новый шаг "Выполнение команды Windows" 93 | cpd -d src -i *.bsl -r pmd -f cpd.xml 94 | 95 | Добавляем послесборочный шаг "Publish duplicate code analysis results" 96 | В поле "Duplicate code results" пишем имя файла cpd.xml 97 | Добавляем расширенный параметр, пока всего один - "Default encoding" 98 | Там пишем UTF-8 99 | Готово, можно выполнять. 100 | Если будет ошибка, то возможно slave-node не видит утилиту cpd, т.к. не обновил path. 101 | Нужно перезапустить подчиненный узел. 102 | В логах будет видно шаги [cpd] и [DRY] 103 | Заходим в задачу, затем в номер сборки и видим там новый тэг "Duplicate code", 104 | а также справа появится диаграмма "Duplicate code trend". 105 | В тэге "Duplicate code" будет список модулей, где нашли дубли. 106 | 107 | Данная утилита в случае обнаружения дублирования кода взводит в консоли флаг ошибки. 108 | Это можно проверить, выполнив в консоли из каталога сборки команду 109 | > echo %ERRORLEVEL% 110 | Там будет число, отличное от нуля. 111 | 112 | Из-за этого сборка будет падать с ошибкой. Чтобы это исправить, добавим "|| exit 0" в команду. 113 | В настройках задачи, там где у нас единственный шаг, пишем: 114 | cpd -d src -i *.bsl -r pmd -f cpd.xml || exit 0 115 | Теперь задача не будет падать. 116 | 117 | 118 | Добавление в сборочную линию. 119 | Добавляем в ту же stage: 120 | 121 | stage ('Статический анализ'){ 122 | steps { 123 | script { 124 | //if (env.BUILD_NUMBER.endsWith("3")) { 125 | build job: 'cyclo', wait: false 126 | build job: 'cpd', wait: false 127 | // } 128 | } 129 | 130 | 131 | 132 | } 133 | } -------------------------------------------------------------------------------- /Block8/Jenkinsfile: -------------------------------------------------------------------------------- 1 | connectionString = "" /*define it without def to make it global. https://stackoverflow.com/questions/45514585/exception-while-executing-groovy-script-from-jenkinsfile-groovy-lang-missingprop*/ 2 | def uccode 3 | def lockParams 4 | 5 | def versionText 6 | def versionValue 7 | 8 | pipeline { 9 | agent { 10 | label 'bdd' 11 | } 12 | environment { 13 | Storage = credentials('Storage_Trade_CiBot') 14 | /* логин и пароль разделенные двоеточием:*/ 15 | /* Storage - login:pass*/ 16 | /* Storage_Usr - логин*/ 17 | /* Storage_Psw - пароль*/ 18 | } 19 | 20 | stages { 21 | stage ('Обновление тестового контура'){ 22 | steps { 23 | timestamps { 24 | script { 25 | connectionString = "\"/S${env.Server1C}\\${env.Database1C}\"" 26 | uccode = "\"123\"" 27 | lockParams = "-lockmessage \"base is blocked\" -lockuccode ${uccode}" 28 | 29 | versionText = readFile encoding: 'UTF-8', file: 'src/cf/VERSION' 30 | versionValue = (versionText =~ /(.*)<\/VERSION>/)[0][1] 31 | } 32 | 33 | cmd("oscript --version") 34 | cmd("deployka session lock -ras ${env.ServerRAS} -db ${env.Database1C} ${lockParams}") 35 | cmd("deployka session kill -ras ${env.ServerRAS} -db ${env.Database1C} ${lockParams}") 36 | cmd("deployka loadrepo ${connectionString} \"${env.StoragePath}\" -storage-user ${env.Storage_Usr} -storage-pwd ${env.Storage_Psw} -uccode \"123\" -storage-ver ${versionValue}") 37 | cmd("deployka dbupdate ${connectionString} -allow-warnings -uccode \"123\"") 38 | cmd("deployka session unlock -ras ${env.ServerRAS} -db ${env.Database1C}") 39 | } 40 | } 41 | } 42 | stage ('Проверка поведения'){ 43 | steps { 44 | timestamps { 45 | cmd("vrunner vanessa --pathvanessa ./tools/vanessa-behavior/vanessa-behavior.epf --vanessasettings ./tools/VBParams.json --workspace . --ibconnection ${connectionString}") 46 | } 47 | } 48 | } 49 | stage ('Дымовое тестирование') { 50 | steps { 51 | timestamps { 52 | cmd("vrunner xunit ./tools/xUnitFor1C/Tests/Smoke --pathxunit ./tools/xUnitFor1C/xddTestRunner.epf --reportsxunit \"ГенераторОтчетаJUnitXML{out/junit.xml}\" --xddExitCodePath ./out/junitstatus.log --ibconnection ${connectionString} --xddConfig ./tools/xunitparams.json") 53 | } 54 | } 55 | } 56 | stage ('Юнит-тестирование') { 57 | steps { 58 | timestamps { 59 | cmd("vrunner xunit ./unitTests/1823244 --pathxunit ./tools/xUnitFor1C/xddTestRunner.epf --reportsxunit \"ГенераторОтчетаJUnitXML{out/unittest.xml}\" --xddExitCodePath ./out/unitteststatus.log --ibconnection ${connectionString}") 60 | } 61 | } 62 | } 63 | stage ('Публикация результатов'){ 64 | steps { 65 | script { 66 | def allurePath = tool name: 'allure', type: 'allure' 67 | cmd("${allurePath}/bin/allure generate -o out/publishHTML/allure-report out/allure") 68 | } 69 | 70 | junit allowEmptyResults: true, testResults: 'out/junit.xml, out/unittest.xml' 71 | 72 | cmd("pickles -f features -o out/publishHTML/pickles -l ru --df dhtml --sn \"Trade\"") 73 | 74 | publishHTML target: [ 75 | allowMissing: false, 76 | alwaysLinkToLastBuild: false, 77 | keepAll: false, 78 | reportDir: 'out/publishHTML', 79 | reportFiles: 'allure-report/index.html,pickles/Index.html', 80 | reportName: 'HTML Report', 81 | reportTitles: 'Отчеты Allure and Pickles' 82 | ] 83 | step([ 84 | $class: 'CucumberReportPublisher', 85 | fileIncludePattern: '*.json', 86 | jsonReportDirectory: 'out/cucumber' 87 | ]) 88 | 89 | step([ 90 | $class: 'CukedoctorPublisher', 91 | featuresDir: 'out/cucumber', 92 | formt: 'HTML', 93 | hideFeaturesSection: false, 94 | hideScenarioKeyword: false, 95 | hideStepTime: false, 96 | hideSummary: false, 97 | hideTags: false, 98 | numbered: true, 99 | sectAnchors: true, 100 | title: 'Living Docs', 101 | toc: 'LEFT' 102 | 103 | ]) 104 | 105 | } 106 | 107 | 108 | } 109 | 110 | stage ('Подготовка дистрибутива') { 111 | steps { 112 | timestamps { 113 | cmd ("packman load-storage \"${env.StoragePath}\" -use-tool1cd -storage-v ${versionValue}") 114 | cmd ("packman make-cf") 115 | cmd ("packman make-dist ./tools/package.edf -setup") 116 | cmd ("packman zip-dist -out out -name-prefix trade19400") 117 | 118 | archiveArtifacts artifacts: 'out/trade19400*.zip', onlyIfSuccessful: true 119 | } 120 | } 121 | } 122 | 123 | } 124 | } 125 | def cmd(command) { 126 | if (isUnix()) { 127 | sh "${command}" 128 | } else { 129 | bat "chcp 65001\n${command}" 130 | } 131 | } -------------------------------------------------------------------------------- /Block9/cyclo.os: -------------------------------------------------------------------------------- 1 | // Обработка предназначена для автоматизированного расчета цикломатической сложности кода 2 | // Адрес публикации на Инфорстарте: http://infostart.ru/public/166182/ 3 | // Вы можете использовать обработку по своему усмотрению в рамках действующего законодательства. 4 | // Единственная просьба: если у вас есть замечания или предложения по улучшению обработки, а также в случае нахождения багов - пишите мне об этом на http://infostart.ru/profile/101097/ 5 | 6 | #Использовать cmdline 7 | #Использовать logos 8 | 9 | Перем МассивСтрокМодуля Экспорт; 10 | Перем ДеревоРезультатовАнализа; 11 | Перем ТекстМодуля; 12 | Перем Лог; 13 | 14 | // функция ищет следующее, после указанного символа, вхождение подстроки 15 | // 16 | // Параметры 17 | // Строка – Строка – строка, в которой нужно искать 18 | // Подстрока – Строка – строка, которую нужно найти 19 | // НачинатьС - Число - номер символа, с которого нужно начинать поиск 20 | // (если не указан, начинает с начала) 21 | // 22 | // Возвращаемое значение: 23 | // Число – номер символа, с которого начинается (очередное) вхождения подстроки в строку 24 | // 25 | Функция НайтиСледующееВхождениеПодстроки(Знач Строка, Знач Подстрока, НачинатьС = 1) Экспорт 26 | Результат = Найти(Сред(ВРег(Строка), НачинатьС), ВРег(Подстрока)); 27 | Если Результат <> 0 Тогда 28 | Результат = Результат + НачинатьС - 1; 29 | КонецЕсли; 30 | 31 | Возврат Результат; 32 | КонецФункции 33 | 34 | // функция ищет предыдущее, перед указанным символом, вхождение подстроки 35 | // 36 | // Параметры 37 | // Строка – Строка – строка, в которой нужно искать 38 | // Подстрока – Строка – строка, которую нужно найти 39 | // НачинатьС - Число - номер символа, с которого нужно начинать поиск 40 | // (если не указан, начинает с конца) 41 | // 42 | // Возвращаемое значение: 43 | // Число – номер символа, с которого начинается (предыдущее) вхождения подстроки в строку 44 | // 45 | Функция НайтиПредыдущееВхождениеПодстроки(Знач Строка, Знач Подстрока, Знач НачинатьС = 0) Экспорт 46 | Строка = ВРег(Строка); 47 | Подстрока = ВРег(Подстрока); 48 | 49 | ДлинаСтроки = СтрДлина(Строка); 50 | ДлинаПодстроки = СтрДлина(Подстрока); 51 | Если НачинатьС = 0 Тогда 52 | НачинатьС = ДлинаСтроки - ДлинаПодстроки + 1; 53 | КонецЕсли; 54 | 55 | Результат = 0; 56 | 57 | Пока НачинатьС > 0 И Результат = 0 Цикл 58 | // сравнивать напрямую нельзя - строки могут быть в разных регистрах 59 | Если Найти(Сред(Строка, НачинатьС, ДлинаПодстроки), Подстрока) = 1 Тогда 60 | // нашли вхождение подстроки 61 | Результат = НачинатьС; 62 | КонецЕсли; 63 | НачинатьС = НачинатьС - 1; 64 | КонецЦикла; 65 | 66 | Возврат Результат; 67 | КонецФункции 68 | 69 | // процедура выполняет удаление всех двойных кавычек в модуле 70 | // 71 | // Параметры 72 | // Текст – Строка – текст анализируемого модуля 73 | // 74 | Процедура УбратьДвойныеКавычки(Текст) Экспорт 75 | Текст = СтрЗаменить(Текст, """""", ""); 76 | КонецПроцедуры 77 | 78 | // процедура выполняет удаление всех комментариев модуля 79 | // 80 | // Параметры 81 | // Текст – Строка – текст анализируемого модуля 82 | // 83 | Процедура УбратьКомментарии(Текст) Экспорт 84 | ПозицияНачалаКомментария = НайтиСледующееВхождениеПодстроки(Текст, "//"); 85 | Пока ПозицияНачалаКомментария <> 0 Цикл 86 | //перед тем, как удалять нужно проверить, что эти слеши не находятся в строке 87 | НачалоТекущейСтроки = НайтиПредыдущееВхождениеПодстроки(Текст, Символы.ПС, ПозицияНачалаКомментария); 88 | Если НачалоТекущейСтроки = 0 Тогда 89 | НачалоТекущейСтроки = 1; 90 | КонецЕсли; 91 | 92 | ТекущаяСтрока = СокрЛ(Сред(Текст, НачалоТекущейСтроки, ПозицияНачалаКомментария - НачалоТекущейСтроки)); 93 | КоличествоКавычек = СтрЧислоВхождений(ТекущаяСтрока, """"); 94 | Если Лев(ТекущаяСтрока, 1) = "|" Тогда 95 | КоличествоКавычек = КоличествоКавычек + 1; 96 | КонецЕсли; 97 | 98 | Если КоличествоКавычек % 2 = 1 Тогда 99 | // найденные слэши находятся внутри строковой константы - это НЕ начало комментария, их можно просто удалить 100 | Текст = Лев(Текст, ПозицияНачалаКомментария - 1) + Сред(Текст, ПозицияНачалаКомментария + 2); 101 | Иначе 102 | // это начало комментария, текст после них до конца строки можно удалить 103 | НачалоСледующейСтроки = НайтиСледующееВхождениеПодстроки(Текст, Символы.ПС, ПозицияНачалаКомментария); 104 | Текст = Лев(Текст, ПозицияНачалаКомментария - 1) + ?(НачалоСледующейСтроки <> 0, Сред(Текст, НачалоСледующейСтроки), ""); 105 | КонецЕсли; 106 | 107 | ПозицияНачалаКомментария = НайтиСледующееВхождениеПодстроки(Текст, "//"); 108 | КонецЦикла; 109 | КонецПроцедуры 110 | 111 | // функция выполняет удаление всех строковых констант модуля 112 | // 113 | // Параметры 114 | // Текст – Строка – текст анализируемого модуля 115 | // 116 | // Возвращаемое значение: 117 | // Число – код возникшей ошибки: 118 | // 1 - нечетное количество кавычек 119 | // 120 | Функция УбратьСтроковыеКонстанты(Текст) Экспорт 121 | Результат = 0; 122 | 123 | КоличествоКавычек = СтрЧислоВхождений(Текст, """"); 124 | 125 | Если КоличествоКавычек % 2 = 1 Тогда 126 | Возврат 1; 127 | КонецЕсли; 128 | 129 | ПозицияНачалаСтроковойКонстанты = 1; 130 | Пока ПозицияНачалаСтроковойКонстанты <> 0 Цикл 131 | ПозицияНачалаСтроковойКонстанты = НайтиСледующееВхождениеПодстроки(Текст, """"); 132 | ПозицияОкончанияСтроковойКонстанты = НайтиСледующееВхождениеПодстроки(Текст, """", ПозицияНачалаСтроковойКонстанты + 1); 133 | 134 | Текст = Лев(Текст, ПозицияНачалаСтроковойКонстанты - 1) + Сред(Текст, ПозицияОкончанияСтроковойКонстанты + 1); 135 | КонецЦикла; 136 | 137 | Возврат Результат; 138 | КонецФункции 139 | 140 | // процедура выполняет удаление всех комментариев модуля 141 | // 142 | // Параметры 143 | // Текст – Строка – текст анализируемого модуля 144 | // Директива - Строка - идентификатор директивы (# или &) 145 | // 146 | Процедура УбратьДирективыКомпиляции(Текст, Директива) Экспорт 147 | ПозицияНачалаДирективы = НайтиСледующееВхождениеПодстроки(Текст, Директива); 148 | Пока ПозицияНачалаДирективы <> 0 Цикл 149 | НачалоТекущейСтроки = НайтиПредыдущееВхождениеПодстроки(Текст, Символы.ПС, ПозицияНачалаДирективы); 150 | Если НачалоТекущейСтроки = 0 Тогда 151 | НачалоТекущейСтроки = 1; 152 | КонецЕсли; 153 | 154 | СтрокаПередХешем = Сред(Текст, НачалоТекущейСтроки, ПозицияНачалаДирективы - НачалоТекущейСтроки); 155 | 156 | // директивы не могут стоять после других команд или текста в строке - перед ними могут быть только незначащие символы 157 | Если СокрЛП(СтрокаПередХешем) = "" Тогда 158 | НачалоСледующейСтроки = НайтиСледующееВхождениеПодстроки(Текст, Символы.ПС, ПозицияНачалаДирективы + 1); 159 | Если НачалоСледующейСтроки = 0 Тогда 160 | НачалоСледующейСтроки = СтрДлина(Текст); 161 | КонецЕсли; 162 | Текст = ?(НачалоТекущейСтроки > 1, Лев(Текст, НачалоТекущейСтроки), "") + Сред(Текст, НачалоСледующейСтроки); 163 | КонецЕсли; 164 | 165 | ПозицияНачалаДирективы = НайтиСледующееВхождениеПодстроки(Текст, Директива, ПозицияНачалаДирективы); 166 | КонецЦикла; 167 | КонецПроцедуры 168 | 169 | // функция выделяет из переданного текста текст следующего метода и возвращает его 170 | // 171 | // Параметры 172 | // Текст – Строка – текст анализируемого модуля 173 | // ИмяМетода - Строка - функция возвращает имя найденного метода 174 | // 175 | // Возвращаемое значение: 176 | // Строка – текст очередного метода 177 | // 178 | Функция ИзвлечьСледующийМетод(Текст, ИмяМетода) 179 | Результат = ""; 180 | ИмяМетода = ""; 181 | КонецМетода = 0; 182 | 183 | Текст = СокрЛ(Текст); 184 | // анализируем следующий метод 185 | ПозицияСкобки = НайтиСледующееВхождениеПодстроки(Текст, "("); 186 | Если ПозицияСкобки <> 0 Тогда 187 | ЗаголовокМетода = Лев(Текст, ПозицияСкобки - 1); 188 | Текст = Сред(Текст, ПозицияСкобки); 189 | 190 | Если ВРег(Лев(ЗаголовокМетода, 9)) = ВРег("Процедура") ИЛИ 191 | ВРег(Лев(ЗаголовокМетода, 9)) = ВРег("Procedure") Тогда 192 | 193 | ИмяМетода = СокрЛП(Сред(ЗаголовокМетода, 11)); 194 | КонецМетодаРусс = НайтиСледующееВхождениеПодстроки(Текст, "КонецПроцедуры"); 195 | КонецМетодаАнгл = НайтиСледующееВхождениеПодстроки(Текст, "EndProcedure"); 196 | Если КонецМетодаРусс <> 0 Тогда 197 | Если КонецМетодаАнгл <> 0 Тогда 198 | Если КонецМетодаРусс < КонецМетодаАнгл Тогда 199 | КонецМетода = КонецМетодаРусс + 14; // 14 = СтрДлина("КонецПроцедуры") 200 | Иначе 201 | КонецМетода = КонецМетодаАнгл + 12; // 12 = СтрДлина("EndProcedure") 202 | КонецЕсли; 203 | Иначе 204 | КонецМетода = КонецМетодаРусс + 14; // 14 = СтрДлина("КонецПроцедуры") 205 | КонецЕсли; 206 | Иначе // КонецМетодаРусс = 0 207 | Если КонецМетодаАнгл <> 0 Тогда 208 | КонецМетода = КонецМетодаАнгл + 12; // 12 = СтрДлина("EndProcedure") 209 | Иначе 210 | ВызватьИсключение "Не удалось найти завершение процедуры " + ИмяМетода; 211 | КонецЕсли; 212 | КонецЕсли; 213 | ИначеЕсли ВРег(Лев(ЗаголовокМетода, 7)) = ВРег("Функция") ИЛИ 214 | ВРег(Лев(ЗаголовокМетода, 8)) = ВРег("Function") Тогда 215 | 216 | Если ВРег(Лев(ЗаголовокМетода, 7)) = ВРег("Функция") Тогда 217 | ИмяМетода = СокрЛП(Сред(ЗаголовокМетода, 8)); 218 | Иначе 219 | ИмяМетода = СокрЛП(Сред(ЗаголовокМетода, 9)); 220 | КонецЕсли; 221 | 222 | КонецМетодаРусс = НайтиСледующееВхождениеПодстроки(Текст, "КонецФункции"); 223 | КонецМетодаАнгл = НайтиСледующееВхождениеПодстроки(Текст, "EndFunction"); 224 | Если КонецМетодаРусс <> 0 Тогда 225 | Если КонецМетодаАнгл <> 0 Тогда 226 | Если КонецМетодаРусс < КонецМетодаАнгл Тогда 227 | КонецМетода = КонецМетодаРусс + 12; // 12 = СтрДлина("КонецФункции") 228 | Иначе 229 | КонецМетода = КонецМетодаАнгл + 11; // 11 = СтрДлина("EndFunction") 230 | КонецЕсли; 231 | Иначе 232 | КонецМетода = КонецМетодаРусс + 12; // 12 = СтрДлина("КонецФункции") 233 | КонецЕсли; 234 | Иначе // КонецМетодаРусс = 0 235 | Если КонецМетодаАнгл <> 0 Тогда 236 | КонецМетода = КонецМетодаАнгл + 11; // 11 = СтрДлина("EndFunction") 237 | Иначе 238 | ВызватьИсключение "Не удалось найти завершение функции " + ИмяМетода; 239 | КонецЕсли; 240 | КонецЕсли; 241 | КонецЕсли; 242 | КонецЕсли; 243 | 244 | Если КонецМетода <> 0 Тогда 245 | Результат = СокрЛП(Лев(Текст, КонецМетода)); 246 | Текст = СокрЛП(Сред(Текст, КонецМетода + 1)); 247 | Иначе 248 | ИмяМетода = "<Инициализация модуля>"; 249 | Результат = СокрЛП(Текст); 250 | Текст = ""; 251 | КонецЕсли; 252 | 253 | Возврат Результат; 254 | КонецФункции 255 | 256 | // функция ищет следующее вхождение Слова в Текст 257 | // 258 | // Параметры 259 | // Текст – Строка – анализируемый текст 260 | // Слово – Строка – искомое слово 261 | // НачинатьС - Число - откуда искать 262 | // 263 | // Возвращаемое значение: 264 | // Число – начало следующего вхождения слова 265 | // 266 | Функция НайтиСледующееВхождениеСлова(Текст, Слово, Знач Курсор = 1) 267 | СловоНайдено = Ложь; 268 | ДлинаСлова = СтрДлина(Слово); 269 | Пока Курсор <> 0 И Не СловоНайдено Цикл 270 | Курсор = НайтиСледующееВхождениеПодстроки(Текст, Слово, Курсор); 271 | //проверим, что это не часть идентификатора 272 | Если Курсор <> 0 Тогда 273 | КодСимволаСлева = КодСимвола(Текст, Курсор - 1); 274 | КодСимволаСправа = КодСимвола(Текст, Курсор + ДлинаСлова); 275 | Если НЕ ( 276 | (КодСимволаСлева >= 97 И КодСимволаСлева <= 122) ИЛИ // a-z 277 | (КодСимволаСлева >= 65 И КодСимволаСлева <= 90) ИЛИ // A-Z 278 | (КодСимволаСлева >= 1040 И КодСимволаСлева <= 1103) ИЛИ // А-Я,а-я 279 | (КодСимволаСлева >= 48 И КодСимволаСлева <= 57) ИЛИ // 0-9 280 | (КодСимволаСлева = 95) ИЛИ // "_" 281 | (КодСимволаСправа >= 97 И КодСимволаСправа <= 122) ИЛИ // a-z 282 | (КодСимволаСправа >= 65 И КодСимволаСправа <= 90) ИЛИ // A-Z 283 | (КодСимволаСправа >= 1040 И КодСимволаСправа <= 1103) ИЛИ // А-Я,а-я 284 | (КодСимволаСправа >= 48 И КодСимволаСправа <= 57) ИЛИ // 0-9 285 | (КодСимволаСправа = 95) // "_" 286 | ) Тогда // это не часть идентификатора 287 | СловоНайдено = Истина; 288 | Иначе 289 | Курсор = Курсор + ДлинаСлова; 290 | КонецЕсли; 291 | КонецЕсли; 292 | КонецЦикла; 293 | Возврат Курсор; 294 | КонецФункции 295 | 296 | // функция считает количество вхождений Слова в Текст 297 | // 298 | // Параметры 299 | // Текст – Строка – анализируемый текст 300 | // Слово – Строка – искомое слово 301 | // 302 | // Возвращаемое значение: 303 | // Число – количество вхождений Слова в Текст 304 | // 305 | Функция ЧислоВхожденийСлова(Текст, Слово) 306 | Если Слово = "" Тогда 307 | Возврат 0; 308 | КонецЕсли; 309 | 310 | Результат = 0; 311 | Курсор = 1; 312 | ДлинаТекста = СтрДлина(Текст); 313 | ДлинаСлова = СтрДлина(Слово); 314 | 315 | Пока Курсор <> 0 Цикл 316 | Курсор = НайтиСледующееВхождениеСлова(Текст, Слово, Курсор); 317 | Если Курсор <> 0 Тогда 318 | Результат = Результат + 1; 319 | Курсор = Курсор + ДлинаСлова; 320 | КонецЕсли; 321 | КонецЦикла; 322 | 323 | Возврат Результат; 324 | КонецФункции 325 | 326 | // процедура вычисляет цикломатическую сложность переданного текста и записывает результаты анализа в узел дерева 327 | // 328 | // Параметры 329 | // Текст – Строка – текст анализируемого модуля 330 | // 331 | Процедура ВычислитьЦикломатическуюСложность(Знач Текст, УзелДереваРезультатов) Экспорт 332 | УбратьДвойныеКавычки(Текст); 333 | УбратьКомментарии(Текст); 334 | Если УбратьСтроковыеКонстанты(Текст) = 1 Тогда 335 | // ошибка при разборе 336 | УзелДереваРезультатов.ИмяМетода = "Нечетное количество кавычек в модуле. Анализ не произведен!"; 337 | Возврат; 338 | КонецЕсли; 339 | УбратьДирективыКомпиляции(Текст, "#"); 340 | УбратьДирективыКомпиляции(Текст, "&"); 341 | 342 | // убираем объявление переменных 343 | НачалоПервогоМетода = СтрДлина(Текст); 344 | Курсор = НайтиСледующееВхождениеПодстроки(Текст, "Процедура"); 345 | НачалоПервогоМетода = Мин(НачалоПервогоМетода, ?(Курсор = 0, НачалоПервогоМетода, Курсор)); 346 | Курсор = НайтиСледующееВхождениеПодстроки(Текст, "Procedure"); 347 | НачалоПервогоМетода = Мин(НачалоПервогоМетода, ?(Курсор = 0, НачалоПервогоМетода, Курсор)); 348 | Курсор = НайтиСледующееВхождениеПодстроки(Текст, "Функция"); 349 | НачалоПервогоМетода = Мин(НачалоПервогоМетода, ?(Курсор = 0, НачалоПервогоМетода, Курсор)); 350 | Курсор = НайтиСледующееВхождениеПодстроки(Текст, "Function"); 351 | НачалоПервогоМетода = Мин(НачалоПервогоМетода, ?(Курсор = 0, НачалоПервогоМетода, Курсор)); 352 | Если НачалоПервогоМетода <> СтрДлина(Текст) Тогда 353 | Текст = Сред(Текст, НачалоПервогоМетода); 354 | КонецЕсли; 355 | 356 | МаксимальнаяСложностьУзлов = 0; 357 | Пока Текст <> "" Цикл 358 | //ОбработкаПрерыванияПользователя(); 359 | ИмяМетода = ""; 360 | Попытка 361 | ТекстМетода = ИзвлечьСледующийМетод(Текст, ИмяМетода); 362 | 363 | ЦикломатическаяСложность = 364 | 1 + ЧислоВхожденийСлова(ТекстМетода, "Тогда") 365 | + ЧислоВхожденийСлова(ТекстМетода, "Then") 366 | + ЧислоВхожденийСлова(ТекстМетода, "Цикл") 367 | + ЧислоВхожденийСлова(ТекстМетода, "Do") 368 | + ЧислоВхожденийСлова(ТекстМетода, "Попытка") 369 | + ЧислоВхожденийСлова(ТекстМетода, "Try") 370 | + ЧислоВхожденийСлова(ТекстМетода, "Возврат") 371 | + ЧислоВхожденийСлова(ТекстМетода, "Return") 372 | + ЧислоВхожденийСлова(ТекстМетода, "ВызватьИсключение") 373 | + ЧислоВхожденийСлова(ТекстМетода, "Raise") 374 | + ЧислоВхожденийСлова(ТекстМетода, "Продолжить") 375 | + ЧислоВхожденийСлова(ТекстМетода, "Continue") 376 | + ЧислоВхожденийСлова(ТекстМетода, "Прервать") 377 | + ЧислоВхожденийСлова(ТекстМетода, "Break") 378 | + ?(Истина, ЧислоВхожденийСлова(ТекстМетода, "?"), 0); 379 | ТекущаяСтрока = УзелДереваРезультатов.Строки.Добавить(); 380 | ТекущаяСтрока.Файл = УзелДереваРезультатов.Файл; 381 | ТекущаяСтрока.ИмяМетода = ИмяМетода; 382 | ТекущаяСтрока.ЦикломатическаяСложность = ЦикломатическаяСложность; 383 | МаксимальнаяСложностьУзлов = Макс(МаксимальнаяСложностьУзлов, ЦикломатическаяСложность); 384 | Исключение 385 | ТекущаяСтрока = УзелДереваРезультатов.Строки.Добавить(); 386 | ТекущаяСтрока.Файл = УзелДереваРезультатов.Файл; 387 | ТекущаяСтрока.ИмяМетода = "Не удалось обработать модуль: " + ИмяМетода; 388 | ТекущаяСтрока.ЦикломатическаяСложность = 0; 389 | КонецПопытки; 390 | КонецЦикла; 391 | УзелДереваРезультатов.ЦикломатическаяСложность = МаксимальнаяСложностьУзлов; 392 | КонецПроцедуры 393 | 394 | // процедура расчитывает цикломатическую сложность реквизита ТекстМодуля 395 | // 396 | Процедура ВычислитьСложностьТекстаМодуля() Экспорт 397 | Лог.Информация("Анализ текста модуля..."); 398 | ДеревоРезультатовАнализа.Строки.Очистить(); 399 | 400 | ТекущийУзел = ДеревоРезультатовАнализа.Строки.Добавить(); 401 | ТекущийУзел.Файл = "<Текст модуля>"; 402 | ТекущийУзел.Путь = ""; 403 | ВычислитьЦикломатическуюСложность(ТекстМодуля, ТекущийУзел); 404 | Лог.Информация(""); 405 | КонецПроцедуры 406 | 407 | // процедура расчитывает цикломатическую сложность модулей файлов каталога 408 | // 409 | // Параметры 410 | // ПутьКаталога – Строка – путь к анализируемому каталогу 411 | // МаскаФайлов – Строка – маска для поиска файлов в каталоге 412 | // 413 | Процедура ВычислитьСложностьМодулейВКаталоге(ПутьКаталога, МаскаФайлов = "", ВключатьПодкаталоги = Ложь) Экспорт 414 | Если Не ЗначениеЗаполнено(ПутьКаталога) Тогда 415 | Возврат; 416 | КонецЕсли; 417 | 418 | Лог.Информация("Поиск файлов..."); 419 | ТекущийФайл = Новый Файл(ПутьКаталога); 420 | 421 | Если ТекущийФайл.ЭтоКаталог() Тогда 422 | МассивФайлов = НайтиФайлы(ПутьКаталога, ?(ЗначениеЗаполнено(МаскаФайлов), МаскаФайлов, "*"), ВключатьПодкаталоги); 423 | Иначе 424 | МассивФайлов = Новый Массив; 425 | МассивФайлов.Добавить(ТекущийФайл); 426 | КонецЕсли; 427 | 428 | Если МассивФайлов.Количество() = 0 Тогда 429 | Лог.Информация("Подходящий файлов не найдено!"); 430 | Возврат; 431 | КонецЕсли; 432 | 433 | ДеревоРезультатовАнализа.Строки.Очистить(); 434 | ТекстовыйФайл = Новый ТекстовыйДокумент; 435 | Для каждого ТекущийФайл Из МассивФайлов Цикл 436 | Лог.Информация("Анализ файла " + ТекущийФайл.ПолноеИмя + "..."); 437 | 438 | Если ТекущийФайл.ЭтоФайл() Тогда 439 | ТекущийУзел = ДеревоРезультатовАнализа.Строки.Добавить(); 440 | ТекущийУзел.Файл = ТекущийФайл.Имя; 441 | ТекущийУзел.Путь = ТекущийФайл.Путь; 442 | ТекстовыйФайл.Прочитать(ТекущийФайл.ПолноеИмя); 443 | ВычислитьЦикломатическуюСложность(ТекстовыйФайл.ПолучитьТекст(), ТекущийУзел); 444 | КонецЕсли; 445 | КонецЦикла; 446 | ТекстовыйФайл = Неопределено; 447 | 448 | Лог.Информация(""); 449 | Лог.Информация("Анализ завершен!"); 450 | КонецПроцедуры 451 | 452 | Парсер = Новый ПарсерАргументовКоманднойСтроки(); 453 | Парсер.ДобавитьПараметр("ПутьКИсходникам"); 454 | Парсер.ДобавитьПараметр("ПутьКЛогу"); 455 | Параметры = Парсер.Разобрать(АргументыКоманднойСтроки); 456 | 457 | Лог = Логирование.ПолучитьЛог("oscript.app.cyclo"); 458 | Аппендер = Новый ВыводЛогаВФайл(); 459 | Аппендер.ОткрытьФайл(Параметры["ПутьКЛогу"]); 460 | Лог.ДобавитьСпособВывода(Аппендер); 461 | 462 | ВыводПоУмолчанию = Новый ВыводЛогаВКонсоль(); 463 | Лог.ДобавитьСпособВывода(ВыводПоУмолчанию); 464 | 465 | Лог.Информация("Я расчётчик цикломатической сложности 466 | | 467 | |"); 468 | 469 | ДеревоРезультатовАнализа = Новый ДеревоЗначений; 470 | ДеревоРезультатовАнализа.Колонки.Добавить("Путь"); 471 | ДеревоРезультатовАнализа.Колонки.Добавить("Файл"); 472 | ДеревоРезультатовАнализа.Колонки.Добавить("ИмяМетода"); 473 | ДеревоРезультатовАнализа.Колонки.Добавить("ЦикломатическаяСложность"); 474 | 475 | ВычислитьСложностьМодулейВКаталоге(Параметры["ПутьКИсходникам"],"*.bsl",Истина); 476 | 477 | СуммаЦикломатикиПоОбъектам = 0; 478 | 479 | Для каждого _строкаДерева из ДеревоРезультатовАнализа.Строки Цикл 480 | 481 | СуммаЦикломатикиПоОбъектам = СуммаЦикломатикиПоОбъектам + _строкаДерева.ЦикломатическаяСложность; 482 | 483 | Лог.Информация(" Файл " + _строкаДерева.Путь + "\" + _строкаДерева.Файл + " cyclo - " + _строкаДерева.ЦикломатическаяСложность) ; 484 | 485 | КонецЦикла; 486 | 487 | Лог.Информация("Средняя цикломатическая сложность " + СуммаЦикломатикиПоОбъектам/ДеревоРезультатовАнализа.Строки.Количество()); 488 | -------------------------------------------------------------------------------- /Block9/Cyclo_KrapivinAndrey.os: -------------------------------------------------------------------------------- 1 | Крапивин Андрей 2 | Это доработанный скрипт https://drive.google.com/file/d/0By-zQ6shEKllM0x2ZWQ1OEhMdXc/view?usp=sharing12 3 | Поправил расчет. Добавил детализацию до процедур/функций. Самое главное - формирует файл ccm.xml для плагина https://wiki.jenkins-ci.org/display/JENKINS/CCM+Plugin3 чтобы красиво выводить статистику(по аналогии с дублированием кода) 4 | Строка запуска oscript ./tools/cyclo.os ./src/ ccm.xml ccm.txt 5 | 6 | 7 | 8 | 9 | // Обработка предназначена для автоматизированного расчета цикломатической сложности кода 10 | // Адрес публикации на Инфорстарте: http://infostart.ru/public/166182/ 11 | // Вы можете использовать обработку по своему усмотрению в рамках действующего законодательства. 12 | // Единственная просьба: если у вас есть замечания или предложения по улучшению обработки, а также в случае нахождения багов - пишите мне об этом на http://infostart.ru/profile/101097/ 13 | 14 | #Использовать cmdline 15 | #Использовать logos 16 | #Использовать strings 17 | 18 | Перем МассивСтрокМодуля Экспорт; 19 | Перем ДеревоРезультатовАнализа; 20 | Перем ТекстМодуля; 21 | Перем Лог; 22 | 23 | // функция ищет следующее, после указанного символа, вхождение подстроки 24 | // 25 | // Параметры 26 | // Строка – Строка – строка, в которой нужно искать 27 | // Подстрока – Строка – строка, которую нужно найти 28 | // НачинатьС - Число - номер символа, с которого нужно начинать поиск 29 | // (если не указан, начинает с начала) 30 | // 31 | // Возвращаемое значение: 32 | // Число – номер символа, с которого начинается (очередное) вхождения подстроки в строку 33 | // 34 | Функция НайтиСледующееВхождениеПодстроки(Знач Строка, Знач Подстрока, НачинатьС = 1) Экспорт 35 | Результат = Найти(Сред(ВРег(Строка), НачинатьС), ВРег(Подстрока)); 36 | Если Результат <> 0 Тогда 37 | Результат = Результат + НачинатьС - 1; 38 | КонецЕсли; 39 | 40 | Возврат Результат; 41 | КонецФункции 42 | 43 | // функция ищет предыдущее, перед указанным символом, вхождение подстроки 44 | // 45 | // Параметры 46 | // Строка – Строка – строка, в которой нужно искать 47 | // Подстрока – Строка – строка, которую нужно найти 48 | // НачинатьС - Число - номер символа, с которого нужно начинать поиск 49 | // (если не указан, начинает с конца) 50 | // 51 | // Возвращаемое значение: 52 | // Число – номер символа, с которого начинается (предыдущее) вхождения подстроки в строку 53 | // 54 | Функция НайтиПредыдущееВхождениеПодстроки(Знач Строка, Знач Подстрока, Знач НачинатьС = 0) Экспорт 55 | Строка = ВРег(Строка); 56 | Подстрока = ВРег(Подстрока); 57 | 58 | ДлинаСтроки = СтрДлина(Строка); 59 | ДлинаПодстроки = СтрДлина(Подстрока); 60 | Если НачинатьС = 0 Тогда 61 | НачинатьС = ДлинаСтроки - ДлинаПодстроки + 1; 62 | КонецЕсли; 63 | 64 | Результат = 0; 65 | 66 | Пока НачинатьС > 0 И Результат = 0 Цикл 67 | // сравнивать напрямую нельзя - строки могут быть в разных регистрах 68 | Если Найти(Сред(Строка, НачинатьС, ДлинаПодстроки), Подстрока) = 1 Тогда 69 | // нашли вхождение подстроки 70 | Результат = НачинатьС; 71 | КонецЕсли; 72 | НачинатьС = НачинатьС - 1; 73 | КонецЦикла; 74 | 75 | Возврат Результат; 76 | КонецФункции 77 | 78 | // процедура выполняет удаление всех двойных кавычек в модуле 79 | // 80 | // Параметры 81 | // Текст – Строка – текст анализируемого модуля 82 | // 83 | Процедура УбратьДвойныеКавычки(Текст) Экспорт 84 | Текст = СтрЗаменить(Текст, """""", ""); 85 | КонецПроцедуры 86 | 87 | // процедура выполняет удаление всех комментариев модуля 88 | // 89 | // Параметры 90 | // Текст – Строка – текст анализируемого модуля 91 | // 92 | Процедура УбратьКомментарии(Текст) Экспорт 93 | ПозицияНачалаКомментария = НайтиСледующееВхождениеПодстроки(Текст, "//"); 94 | Пока ПозицияНачалаКомментария <> 0 Цикл 95 | //перед тем, как удалять нужно проверить, что эти слеши не находятся в строке 96 | НачалоТекущейСтроки = НайтиПредыдущееВхождениеПодстроки(Текст, Символы.ПС, ПозицияНачалаКомментария); 97 | Если НачалоТекущейСтроки = 0 Тогда 98 | НачалоТекущейСтроки = 1; 99 | КонецЕсли; 100 | 101 | ТекущаяСтрока = СокрЛ(Сред(Текст, НачалоТекущейСтроки, ПозицияНачалаКомментария - НачалоТекущейСтроки)); 102 | КоличествоКавычек = СтрЧислоВхождений(ТекущаяСтрока, """"); 103 | Если Лев(ТекущаяСтрока, 1) = "|" Тогда 104 | КоличествоКавычек = КоличествоКавычек + 1; 105 | КонецЕсли; 106 | 107 | Если КоличествоКавычек % 2 = 1 Тогда 108 | // найденные слэши находятся внутри строковой константы - это НЕ начало комментария, их можно просто удалить 109 | Текст = Лев(Текст, ПозицияНачалаКомментария - 1) + Сред(Текст, ПозицияНачалаКомментария + 2); 110 | Иначе 111 | // это начало комментария, текст после них до конца строки можно удалить 112 | НачалоСледующейСтроки = НайтиСледующееВхождениеПодстроки(Текст, Символы.ПС, ПозицияНачалаКомментария); 113 | Текст = Лев(Текст, ПозицияНачалаКомментария - 1) + ?(НачалоСледующейСтроки <> 0, Сред(Текст, НачалоСледующейСтроки), ""); 114 | КонецЕсли; 115 | 116 | ПозицияНачалаКомментария = НайтиСледующееВхождениеПодстроки(Текст, "//"); 117 | КонецЦикла; 118 | КонецПроцедуры 119 | 120 | // функция выполняет удаление всех строковых констант модуля 121 | // 122 | // Параметры 123 | // Текст – Строка – текст анализируемого модуля 124 | // 125 | // Возвращаемое значение: 126 | // Число – код возникшей ошибки: 127 | // 1 - нечетное количество кавычек 128 | // 129 | Функция УбратьСтроковыеКонстанты(Текст) Экспорт 130 | Результат = 0; 131 | 132 | КоличествоКавычек = СтрЧислоВхождений(Текст, """"); 133 | 134 | Если КоличествоКавычек % 2 = 1 Тогда 135 | Возврат 1; 136 | КонецЕсли; 137 | 138 | ПозицияНачалаСтроковойКонстанты = 1; 139 | Пока ПозицияНачалаСтроковойКонстанты <> 0 Цикл 140 | ПозицияНачалаСтроковойКонстанты = НайтиСледующееВхождениеПодстроки(Текст, """"); 141 | ПозицияОкончанияСтроковойКонстанты = НайтиСледующееВхождениеПодстроки(Текст, """", ПозицияНачалаСтроковойКонстанты + 1); 142 | 143 | Текст = Лев(Текст, ПозицияНачалаСтроковойКонстанты - 1) + Сред(Текст, ПозицияОкончанияСтроковойКонстанты + 1); 144 | КонецЦикла; 145 | 146 | Возврат Результат; 147 | КонецФункции 148 | 149 | // процедура выполняет удаление всех комментариев модуля 150 | // 151 | // Параметры 152 | // Текст – Строка – текст анализируемого модуля 153 | // Директива - Строка - идентификатор директивы (# или &) 154 | // 155 | Процедура УбратьДирективыКомпиляции(Текст, Директива) Экспорт 156 | ПозицияНачалаДирективы = НайтиСледующееВхождениеПодстроки(Текст, Директива); 157 | Пока ПозицияНачалаДирективы <> 0 Цикл 158 | НачалоТекущейСтроки = НайтиПредыдущееВхождениеПодстроки(Текст, Символы.ПС, ПозицияНачалаДирективы); 159 | Если НачалоТекущейСтроки = 0 Тогда 160 | НачалоТекущейСтроки = 1; 161 | КонецЕсли; 162 | 163 | СтрокаПередХешем = Сред(Текст, НачалоТекущейСтроки, ПозицияНачалаДирективы - НачалоТекущейСтроки); 164 | 165 | // директивы не могут стоять после других команд или текста в строке - перед ними могут быть только незначащие символы 166 | Если СокрЛП(СтрокаПередХешем) = "" Тогда 167 | НачалоСледующейСтроки = НайтиСледующееВхождениеПодстроки(Текст, Символы.ПС, ПозицияНачалаДирективы + 1); 168 | Если НачалоСледующейСтроки = 0 Тогда 169 | НачалоСледующейСтроки = СтрДлина(Текст); 170 | КонецЕсли; 171 | Текст = ?(НачалоТекущейСтроки > 1, Лев(Текст, НачалоТекущейСтроки), "") + Сред(Текст, НачалоСледующейСтроки); 172 | КонецЕсли; 173 | 174 | ПозицияНачалаДирективы = НайтиСледующееВхождениеПодстроки(Текст, Директива, ПозицияНачалаДирективы); 175 | КонецЦикла; 176 | КонецПроцедуры 177 | 178 | // функция выделяет из переданного текста текст следующего метода и возвращает его 179 | // 180 | // Параметры 181 | // Текст – Строка – текст анализируемого модуля 182 | // ИмяМетода - Строка - функция возвращает имя найденного метода 183 | // НачалоБлока - Число - с какой строки начинается анализируемый блок 184 | // КонецБлока - Число - какой строкой заканчивается 185 | // 186 | // Возвращаемое значение: 187 | // Строка – текст очередного метода 188 | // 189 | Функция ИзвлечьСледующийМетод(Текст, ИмяМетода, ЭтоФункция, НачалоБлока, КонецБлока) 190 | Результат = ""; 191 | ИмяМетода = ""; 192 | КонецМетода = 0; 193 | 194 | // анализируем следующий метод 195 | ПозицияСкобки = НайтиСледующееВхождениеПодстроки(Текст, "("); 196 | Если ПозицияСкобки <> 0 Тогда 197 | ЗаголовокМетода = Лев(Текст, ПозицияСкобки - 1); 198 | НачалоБлока = НачалоБлока + СтрЧислоВхождений(ЗаголовокМетода, Символы.ПС); 199 | ЗаголовокМетода = СокрЛП(ЗаголовокМетода); 200 | Текст = Сред(Текст, ПозицияСкобки); 201 | 202 | Если ВРег(Лев(ЗаголовокМетода, 9)) = ВРег("Процедура") ИЛИ 203 | ВРег(Лев(ЗаголовокМетода, 9)) = ВРег("Procedure") Тогда 204 | 205 | ЭтоФункция = Ложь; 206 | ИмяМетода = СокрЛП(Сред(ЗаголовокМетода, 11)); 207 | КонецМетодаРусс = НайтиСледующееВхождениеПодстроки(Текст, "КонецПроцедуры"); 208 | КонецМетодаАнгл = НайтиСледующееВхождениеПодстроки(Текст, "EndProcedure"); 209 | Если КонецМетодаРусс <> 0 Тогда 210 | Если КонецМетодаАнгл <> 0 Тогда 211 | Если КонецМетодаРусс < КонецМетодаАнгл Тогда 212 | КонецМетода = КонецМетодаРусс + 14; // 14 = СтрДлина("КонецПроцедуры") 213 | Иначе 214 | КонецМетода = КонецМетодаАнгл + 12; // 12 = СтрДлина("EndProcedure") 215 | КонецЕсли; 216 | Иначе 217 | КонецМетода = КонецМетодаРусс + 14; // 14 = СтрДлина("КонецПроцедуры") 218 | КонецЕсли; 219 | Иначе // КонецМетодаРусс = 0 220 | Если КонецМетодаАнгл <> 0 Тогда 221 | КонецМетода = КонецМетодаАнгл + 12; // 12 = СтрДлина("EndProcedure") 222 | Иначе 223 | ВызватьИсключение "Не удалось найти завершение процедуры " + ИмяМетода; 224 | КонецЕсли; 225 | КонецЕсли; 226 | ИначеЕсли ВРег(Лев(ЗаголовокМетода, 7)) = ВРег("Функция") ИЛИ 227 | ВРег(Лев(ЗаголовокМетода, 8)) = ВРег("Function") Тогда 228 | ЭтоФункция = Истина; 229 | Если ВРег(Лев(ЗаголовокМетода, 7)) = ВРег("Функция") Тогда 230 | ИмяМетода = СокрЛП(Сред(ЗаголовокМетода, 8)); 231 | Иначе 232 | ИмяМетода = СокрЛП(Сред(ЗаголовокМетода, 9)); 233 | КонецЕсли; 234 | 235 | КонецМетодаРусс = НайтиСледующееВхождениеПодстроки(Текст, "КонецФункции"); 236 | КонецМетодаАнгл = НайтиСледующееВхождениеПодстроки(Текст, "EndFunction"); 237 | Если КонецМетодаРусс <> 0 Тогда 238 | Если КонецМетодаАнгл <> 0 Тогда 239 | Если КонецМетодаРусс < КонецМетодаАнгл Тогда 240 | КонецМетода = КонецМетодаРусс + 12; // 12 = СтрДлина("КонецФункции") 241 | Иначе 242 | КонецМетода = КонецМетодаАнгл + 11; // 11 = СтрДлина("EndFunction") 243 | КонецЕсли; 244 | Иначе 245 | КонецМетода = КонецМетодаРусс + 12; // 12 = СтрДлина("КонецФункции") 246 | КонецЕсли; 247 | Иначе // КонецМетодаРусс = 0 248 | ЭтоФункция = Ложь; 249 | Если КонецМетодаАнгл <> 0 Тогда 250 | КонецМетода = КонецМетодаАнгл + 11; // 11 = СтрДлина("EndFunction") 251 | Иначе 252 | ВызватьИсключение "Не удалось найти завершение функции " + ИмяМетода; 253 | КонецЕсли; 254 | КонецЕсли; 255 | КонецЕсли; 256 | КонецЕсли; 257 | 258 | Если КонецМетода <> 0 Тогда 259 | Результат = СокрЛП(Лев(Текст, КонецМетода)); 260 | КонецБлока = НачалоБлока + СтрЧислоВхождений(Результат, Символы.ПС); 261 | Текст = Сред(Текст, КонецМетода + 1); 262 | Иначе 263 | ИмяМетода = "<Инициализация модуля>"; 264 | КонецБлока = НачалоБлока + СтрЧислоВхождений(Текст, Символы.ПС); 265 | Результат = СокрЛП(Текст); 266 | Текст = ""; 267 | КонецЕсли; 268 | 269 | Возврат Результат; 270 | КонецФункции 271 | 272 | // функция ищет следующее вхождение Слова в Текст 273 | // 274 | // Параметры 275 | // Текст – Строка – анализируемый текст 276 | // Слово – Строка – искомое слово 277 | // НачинатьС - Число - откуда искать 278 | // 279 | // Возвращаемое значение: 280 | // Число – начало следующего вхождения слова 281 | // 282 | Функция НайтиСледующееВхождениеСлова(Текст, Слово, Знач Курсор = 1) 283 | СловоНайдено = Ложь; 284 | ДлинаСлова = СтрДлина(Слово); 285 | Пока Курсор <> 0 И Не СловоНайдено Цикл 286 | Курсор = НайтиСледующееВхождениеПодстроки(Текст, Слово, Курсор); 287 | //проверим, что это не часть идентификатора 288 | Если Курсор <> 0 Тогда 289 | КодСимволаСлева = КодСимвола(Текст, Курсор - 1); 290 | КодСимволаСправа = КодСимвола(Текст, Курсор + ДлинаСлова); 291 | Если НЕ ( 292 | (КодСимволаСлева >= 97 И КодСимволаСлева <= 122) ИЛИ // a-z 293 | (КодСимволаСлева >= 65 И КодСимволаСлева <= 90) ИЛИ // A-Z 294 | (КодСимволаСлева >= 1040 И КодСимволаСлева <= 1103) ИЛИ // А-Я,а-я 295 | (КодСимволаСлева >= 48 И КодСимволаСлева <= 57) ИЛИ // 0-9 296 | (КодСимволаСлева = 95) ИЛИ // "_" 297 | (КодСимволаСправа >= 97 И КодСимволаСправа <= 122) ИЛИ // a-z 298 | (КодСимволаСправа >= 65 И КодСимволаСправа <= 90) ИЛИ // A-Z 299 | (КодСимволаСправа >= 1040 И КодСимволаСправа <= 1103) ИЛИ // А-Я,а-я 300 | (КодСимволаСправа >= 48 И КодСимволаСправа <= 57) ИЛИ // 0-9 301 | (КодСимволаСправа = 95) // "_" 302 | ) Тогда // это не часть идентификатора 303 | СловоНайдено = Истина; 304 | Иначе 305 | Курсор = Курсор + ДлинаСлова; 306 | КонецЕсли; 307 | КонецЕсли; 308 | КонецЦикла; 309 | Возврат Курсор; 310 | КонецФункции 311 | 312 | // процедура вычисляет цикломатическую сложность переданного текста и записывает результаты анализа в узел дерева 313 | // 314 | // Параметры 315 | // Текст – Строка – текст анализируемого модуля 316 | // 317 | Процедура ВычислитьЦикломатическуюСложность(Знач Текст, УзелДереваРезультатов) Экспорт 318 | УбратьДвойныеКавычки(Текст); 319 | УбратьКомментарии(Текст); 320 | Если УбратьСтроковыеКонстанты(Текст) = 1 Тогда 321 | // ошибка при разборе 322 | УзелДереваРезультатов.ИмяМетода = "Нечетное количество кавычек в модуле. Анализ не произведен!"; 323 | Возврат; 324 | КонецЕсли; 325 | УбратьДирективыКомпиляции(Текст, "#"); 326 | УбратьДирективыКомпиляции(Текст, "&"); 327 | 328 | // убираем объявление переменных 329 | НачалоПервогоМетода = СтрДлина(Текст); 330 | Курсор = НайтиСледующееВхождениеПодстроки(Текст, "Процедура"); 331 | НачалоПервогоМетода = Мин(НачалоПервогоМетода, ?(Курсор = 0, НачалоПервогоМетода, Курсор)); 332 | Курсор = НайтиСледующееВхождениеПодстроки(Текст, "Procedure"); 333 | НачалоПервогоМетода = Мин(НачалоПервогоМетода, ?(Курсор = 0, НачалоПервогоМетода, Курсор)); 334 | Курсор = НайтиСледующееВхождениеПодстроки(Текст, "Функция"); 335 | НачалоПервогоМетода = Мин(НачалоПервогоМетода, ?(Курсор = 0, НачалоПервогоМетода, Курсор)); 336 | Курсор = НайтиСледующееВхождениеПодстроки(Текст, "Function"); 337 | НачалоПервогоМетода = Мин(НачалоПервогоМетода, ?(Курсор = 0, НачалоПервогоМетода, Курсор)); 338 | Если НачалоПервогоМетода <> СтрДлина(Текст) Тогда 339 | Остаток = Лев(Текст, НачалоПервогоМетода-1); 340 | Текст = Сред(Текст, НачалоПервогоМетода); 341 | КонецЕсли; 342 | НачалоМетода = СтрЧислоВхождений(Остаток, Символы.ПС)+1; 343 | КонецМетода = 0; 344 | МаксимальнаяСложностьУзлов = 0; 345 | Пока Текст <> "" Цикл 346 | //ОбработкаПрерыванияПользователя(); 347 | ИмяМетода = ""; 348 | ЭтоФункция = Ложь; 349 | Попытка 350 | ТекстМетода = ИзвлечьСледующийМетод(Текст, ИмяМетода, ЭтоФункция, НачалоМетода, КонецМетода); 351 | 352 | ЦикломатическаяСложность = 353 | 1 + СтрЧислоВхождений(ТекстМетода, "Тогда") 354 | + СтрЧислоВхождений(ТекстМетода, "Then") 355 | + СтрЧислоВхождений(ТекстМетода, "Цикл") 356 | + СтрЧислоВхождений(ТекстМетода, "Do") 357 | + СтрЧислоВхождений(ТекстМетода, "Попытка") 358 | + СтрЧислоВхождений(ТекстМетода, "Try") 359 | + СтрЧислоВхождений(ТекстМетода, "Возврат") - ?(ЭтоФункция, 1, 0) 360 | + СтрЧислоВхождений(ТекстМетода, "Return") - ?(ЭтоФункция, 1, 0) 361 | + СтрЧислоВхождений(ТекстМетода, "ВызватьИсключение") 362 | + СтрЧислоВхождений(ТекстМетода, "Raise") 363 | + СтрЧислоВхождений(ТекстМетода, "Продолжить") 364 | + СтрЧислоВхождений(ТекстМетода, "Continue") 365 | + СтрЧислоВхождений(ТекстМетода, "Прервать") 366 | + СтрЧислоВхождений(ТекстМетода, "Break") 367 | + ?(Истина, СтрЧислоВхождений(ТекстМетода, "?"), 0); 368 | ТекущаяСтрока = УзелДереваРезультатов.Строки.Добавить(); 369 | ТекущаяСтрока.Файл = УзелДереваРезультатов.Файл; 370 | ТекущаяСтрока.Путь = УзелДереваРезультатов.Путь; 371 | ТекущаяСтрока.ИмяМетода = ИмяМетода; 372 | ТекущаяСтрока.ЦикломатическаяСложность = ЦикломатическаяСложность; 373 | ТекущаяСтрока.НачалоБлока = НачалоМетода; 374 | ТекущаяСтрока.КонецБлока = КонецМетода; 375 | ТекущаяСтрока.Смещение = КонецМетода-НачалоМетода; 376 | МаксимальнаяСложностьУзлов = Макс(МаксимальнаяСложностьУзлов, ЦикломатическаяСложность); 377 | НачалоМетода = КонецМетода+1; 378 | Исключение 379 | ТекущаяСтрока = УзелДереваРезультатов.Строки.Добавить(); 380 | ТекущаяСтрока.Файл = УзелДереваРезультатов.Файл; 381 | ТекущаяСтрока.ИмяМетода = "Не удалось обработать модуль: " + ИмяМетода; 382 | ТекущаяСтрока.НачалоБлока = НачалоМетода; 383 | ТекущаяСтрока.КонецБлока = КонецМетода; 384 | ТекущаяСтрока.Смещение = КонецМетода-НачалоМетода; 385 | ТекущаяСтрока.ЦикломатическаяСложность = 0; 386 | НачалоМетода = КонецМетода; 387 | КонецПопытки; 388 | КонецЦикла; 389 | УзелДереваРезультатов.ЦикломатическаяСложность = МаксимальнаяСложностьУзлов; 390 | КонецПроцедуры 391 | 392 | // процедура расчитывает цикломатическую сложность реквизита ТекстМодуля 393 | // 394 | Процедура ВычислитьСложностьТекстаМодуля(Узел, ТекстМодуля) Экспорт 395 | Лог.Информация("Анализ текста модуля..."); 396 | ТекущийУзел = Узел.Строки.Добавить(); 397 | ТекущийУзел.Файл = Узел.Файл; 398 | ТекущийУзел.Путь = Узел.Путь; 399 | ВычислитьЦикломатическуюСложность(ТекстМодуля, ТекущийУзел); 400 | КонецПроцедуры 401 | 402 | // процедура расчитывает цикломатическую сложность модулей файлов каталога 403 | // 404 | // Параметры 405 | // ПутьКаталога – Строка – путь к анализируемому каталогу 406 | // МаскаФайлов – Строка – маска для поиска файлов в каталоге 407 | // 408 | Процедура ВычислитьСложностьМодулейВКаталоге(ПутьКаталога, МаскаФайлов = "", ВключатьПодкаталоги = Ложь) Экспорт 409 | Если Не ЗначениеЗаполнено(ПутьКаталога) Тогда 410 | Возврат; 411 | КонецЕсли; 412 | 413 | Лог.Информация("Поиск файлов..."); 414 | ТекущийФайл = Новый Файл(ПутьКаталога); 415 | 416 | Если ТекущийФайл.ЭтоКаталог() Тогда 417 | МассивФайлов = НайтиФайлы(ПутьКаталога, ?(ЗначениеЗаполнено(МаскаФайлов), МаскаФайлов, "*"), ВключатьПодкаталоги); 418 | Иначе 419 | МассивФайлов = Новый Массив; 420 | МассивФайлов.Добавить(ТекущийФайл); 421 | КонецЕсли; 422 | 423 | Если МассивФайлов.Количество() = 0 Тогда 424 | Лог.Информация("Подходящий файлов не найдено!"); 425 | Возврат; 426 | КонецЕсли; 427 | 428 | ДеревоРезультатовАнализа.Строки.Очистить(); 429 | ТекстовыйФайл = Новый ТекстовыйДокумент; 430 | Для каждого ТекущийФайл Из МассивФайлов Цикл 431 | Лог.Информация("Анализ файла " + ТекущийФайл.ПолноеИмя + "..."); 432 | 433 | Если ТекущийФайл.ЭтоФайл() Тогда 434 | ТекущийУзел = ДеревоРезультатовАнализа.Строки.Добавить(); 435 | ТекущийУзел.Файл = ТекущийФайл.Имя; 436 | ТекущийУзел.Путь = ТекущийФайл.Путь; 437 | ТекстовыйФайл.Прочитать(ТекущийФайл.ПолноеИмя); 438 | ТекстМодуля = ТекстовыйФайл.ПолучитьТекст(); 439 | ВычислитьСложностьТекстаМодуля(ТекущийУзел, ТекстМодуля); 440 | КонецЕсли; 441 | КонецЦикла; 442 | ТекстовыйФайл = Неопределено; 443 | 444 | Лог.Информация("Анализ завершен!"); 445 | КонецПроцедуры 446 | 447 | Функция ОпределитьУровеньПроблемы(ЦикломатическаяСложность) 448 | Если Число(ЦикломатическаяСложность)>=15 Тогда 449 | Возврат "F"; 450 | ИначеЕсли Число(ЦикломатическаяСложность)>=10 Тогда 451 | Возврат "D" 452 | ИначеЕсли Число(ЦикломатическаяСложность)>=5 Тогда 453 | Возврат "C" 454 | ИначеЕсли Число(ЦикломатическаяСложность)>1 Тогда 455 | Возврат "B"; 456 | Иначе 457 | Возврат "A"; 458 | КонецЕсли; 459 | КонецФункции 460 | 461 | Процедура СформироватьФайлОтчетаCCM(ПутьКФайлу) Экспорт 462 | ЗаписьXML = Новый ЗаписьXML; 463 | ЗаписьXML.ОткрытьФайл(ПутьКФайлу,"UTF-8",Ложь); 464 | ЗаписьXML.ЗаписатьНачалоЭлемента("ccm"); 465 | Для Каждого ОбъектАнализа из ДеревоРезультатовАнализа.Строки Цикл 466 | Для Каждого Модуль из ОбъектАнализа.Строки Цикл 467 | Для Каждого ПроцФунк Из Модуль.Строки Цикл 468 | Если ПроцФунк.ЦикломатическаяСложность = 1 Тогда Продолжить КонецЕсли; 469 | ЗаписьXML.ЗаписатьНачалоЭлемента("metric"); 470 | ЗаписьXML.ЗаписатьНачалоЭлемента("complexity"); 471 | ЗаписьXML.ЗаписатьТекст(строка(ПроцФунк.ЦикломатическаяСложность)); 472 | ЗаписьXML.ЗаписатьКонецЭлемента(); 473 | ЗаписьXML.ЗаписатьНачалоЭлемента("unit"); 474 | ЗаписьXML.ЗаписатьТекст(ПроцФунк.ИмяМетода); 475 | ЗаписьXML.ЗаписатьКонецЭлемента(); 476 | ЗаписьXML.ЗаписатьНачалоЭлемента("classification"); 477 | ЗаписьXML.ЗаписатьТекст(ОпределитьУровеньПроблемы(ПроцФунк.ЦикломатическаяСложность)); 478 | ЗаписьXML.ЗаписатьКонецЭлемента(); 479 | ЗаписьXML.ЗаписатьНачалоЭлемента("file"); 480 | ЗаписьXML.ЗаписатьТекст(ПроцФунк.Путь+ПроцФунк.Файл); 481 | ЗаписьXML.ЗаписатьКонецЭлемента(); 482 | ЗаписьXML.ЗаписатьНачалоЭлемента("startLineNumber"); 483 | ЗаписьXML.ЗаписатьТекст(ПроцФунк.НачалоБлока); 484 | ЗаписьXML.ЗаписатьКонецЭлемента(); 485 | ЗаписьXML.ЗаписатьНачалоЭлемента("endLineNumber"); 486 | ЗаписьXML.ЗаписатьТекст(ПроцФунк.КонецБлока); 487 | ЗаписьXML.ЗаписатьКонецЭлемента(); 488 | ЗаписьXML.ЗаписатьКонецЭлемента(); 489 | КонецЦикла; 490 | КонецЦикла; 491 | КонецЦикла; 492 | ЗаписьXML.ЗаписатьКонецЭлемента(); 493 | ЗаписьXML.Закрыть(); 494 | 495 | //Дополнительные преобразования 496 | Чтение = Новый ЧтениеТекста(ПутьКФайлу, "utf-8"); 497 | Текст = Чтение.Прочитать(); 498 | Чтение.Закрыть(); 499 | Запись = Новый ТекстовыйДокумент; 500 | Запись.УстановитьТекст(Текст); 501 | Запись.Записать(ПутьКФайлу, "utf-8", Символы.ПС); 502 | КонецПроцедуры 503 | 504 | Процедура СформироватьФайлОтчетаCheckStyle(ПутьКФайлу) 505 | ЗаписьXML = Новый ЗаписьXML; 506 | ЗаписьXML.ОткрытьФайл(ПутьКФайлу,"UTF-8",Ложь); 507 | ЗаписьXML.ЗаписатьНачалоЭлемента("checkstyle"); 508 | Для Каждого ОбъектАнализа из ДеревоРезультатовАнализа.Строки Цикл 509 | Для Каждого Модуль из ОбъектАнализа.Строки Цикл 510 | ЗаписьXML.ЗаписатьНачалоЭлемента("file"); 511 | ЗаписьXML.ЗаписатьАтрибут("name", Модуль.Путь+Модуль.Файл); 512 | Для Каждого ПроцФунк Из Модуль.Строки Цикл 513 | Если ПроцФунк.ЦикломатическаяСложность>10 Тогда 514 | ЗаписьXML.ЗаписатьНачалоЭлемента("error"); 515 | ЗаписьXML.ЗаписатьАтрибут("line", ПроцФунк.НачалоБлока); 516 | ЗаписьXML.ЗаписатьАтрибут("severity", "error"); 517 | ЗаписьXML.ЗаписатьАтрибут("message", "Сложность "+ПроцФунк.ЦикломатическаяСложность+". Допустимая 10"); 518 | ЗаписьXML.ЗаписатьАтрибут("source", "Здравый смысл"); 519 | ЗаписьXML.ЗаписатьКонецЭлемента(); 520 | ИначеЕсли ПроцФунк.ЦикломатическаяСложность>5 Тогда 521 | ЗаписьXML.ЗаписатьНачалоЭлемента("error"); 522 | ЗаписьXML.ЗаписатьАтрибут("line", ПроцФунк.НачалоБлока); 523 | ЗаписьXML.ЗаписатьАтрибут("severity", "waring"); 524 | ЗаписьXML.ЗаписатьАтрибут("message", "Сложность "+ПроцФунк.ЦикломатическаяСложность+". Допустимая 10"); 525 | ЗаписьXML.ЗаписатьАтрибут("source", "Здравый смысл"); 526 | ЗаписьXML.ЗаписатьКонецЭлемента(); 527 | КонецЕсли 528 | КонецЦикла; 529 | ЗаписьXML.ЗаписатьКонецЭлемента(); 530 | КонецЦикла; 531 | КонецЦикла; 532 | ЗаписьXML.ЗаписатьКонецЭлемента(); 533 | ЗаписьXML.Закрыть(); 534 | 535 | //Дополнительные преобразования 536 | Чтение = Новый ЧтениеТекста(ПутьКФайлу, "utf-8"); 537 | Текст = Чтение.Прочитать(); 538 | Чтение.Закрыть(); 539 | Запись = Новый ТекстовыйДокумент; 540 | Запись.УстановитьТекст(Текст); 541 | Запись.Записать(ПутьКФайлу, "utf-8", Символы.ПС); 542 | 543 | ОБ_ДД=Новый ДвоичныеДанные(ПутьКФайлу); 544 | Стр_Base64=Base64Строка(ОБ_ДД); 545 | ОБ_ДД=Base64Значение(Сред(Стр_Base64,5)); 546 | ОБ_ДД.Записать(ПутьКФайлу); 547 | 548 | КонецПроцедуры 549 | 550 | Парсер = Новый ПарсерАргументовКоманднойСтроки(); 551 | Парсер.ДобавитьПараметр("ПутьКИсходникам"); 552 | Парсер.ДобавитьПараметр("ПутьКОтчетуCCM"); 553 | Парсер.ДобавитьПараметр("ПутьКОтчетуCheckstyle"); 554 | Парсер.ДобавитьПараметр("ПутьКЛогу"); 555 | Параметры = Парсер.Разобрать(АргументыКоманднойСтроки); 556 | 557 | Лог = Логирование.ПолучитьЛог("oscript.app.cyclo"); 558 | Аппендер = Новый ВыводЛогаВФайл(); 559 | Аппендер.ОткрытьФайл(Параметры["ПутьКЛогу"]); 560 | Лог.ДобавитьСпособВывода(Аппендер); 561 | 562 | ВыводПоУмолчанию = Новый ВыводЛогаВКонсоль(); 563 | Лог.ДобавитьСпособВывода(ВыводПоУмолчанию); 564 | 565 | Лог.Информация("Расчет цикломатической сложности"); 566 | 567 | ДеревоРезультатовАнализа = Новый ДеревоЗначений; 568 | ДеревоРезультатовАнализа.Колонки.Добавить("Путь"); 569 | ДеревоРезультатовАнализа.Колонки.Добавить("Файл"); 570 | ДеревоРезультатовАнализа.Колонки.Добавить("ИмяМетода"); 571 | ДеревоРезультатовАнализа.Колонки.Добавить("ЦикломатическаяСложность"); 572 | ДеревоРезультатовАнализа.Колонки.Добавить("НачалоБлока"); 573 | ДеревоРезультатовАнализа.Колонки.Добавить("КонецБлока"); 574 | ДеревоРезультатовАнализа.Колонки.Добавить("Смещение"); 575 | 576 | ВычислитьСложностьМодулейВКаталоге(Параметры["ПутьКИсходникам"],"*.bsl",Истина); 577 | 578 | СформироватьФайлОтчетаCCM(Параметры["ПутьКОтчетуCCM"]); 579 | СформироватьФайлОтчетаCheckStyle(Параметры["ПутьКОтчетуCheckstyle"]); 580 | 581 | СуммаЦикломатикиПоОбъектам = 0; 582 | 583 | Сч=0; 584 | Для каждого _строкаДерева из ДеревоРезультатовАнализа.Строки Цикл 585 | Для каждого _строкаМодуля из _строкаДерева.Строки Цикл 586 | СуммаЦикломатикиПоОбъектам = СуммаЦикломатикиПоОбъектам + _строкаМодуля.ЦикломатическаяСложность; 587 | Лог.Информация(" Файл " + _строкаМодуля.Путь + _строкаМодуля.Файл + " cyclo - " + _строкаМодуля.ЦикломатическаяСложность) ; 588 | Сч=Сч+1; 589 | КонецЦикла; 590 | КонецЦикла; 591 | 592 | Лог.Информация("Средняя цикломатическая сложность " + СуммаЦикломатикиПоОбъектам/Сч); -------------------------------------------------------------------------------- /src/ReadXLSX/ЧтениеXLSXбезВК/Form/Форма/Форма.bsl: -------------------------------------------------------------------------------- 1 | 2 | &НаКлиенте 3 | Процедура ПрочитатьXLSX(Команда) 4 | ФайлEXCEL= "c:\techjourn\micex.xlsx"; 5 | ИмяНомерЛиста = Новый Структура ("ИмяЛиста, НомерЛиста","Лист1", 1); 6 | СтрокаЗаголовка = 1; 7 | НачСтрока = 0; 8 | КонСтрока = 0; 9 | КолвоСтрокExcel = 0; 10 | ЗагрузитьМетодом_NativeXLSX_НаСервере(ФайлEXCEL, ИмяНомерЛиста, СтрокаЗаголовка, НачСтрока, КонСтрока, КолвоСтрокExcel); 11 | КонецПроцедуры 12 | 13 | 14 | //https://infostart.ru/public/225624/ 15 | 16 | 17 | 18 | &НаСервере 19 | Процедура ЗагрузитьМетодом_NativeXLSX_НаСервере(ФайлEXCEL, ИмяНомерЛиста, СтрокаЗаголовка, НачСтрока, КонСтрока, КолвоСтрокExcel) 20 | ТаблицаРезультат = ЗагрузитьМетодом_NativeXLSX(ФайлEXCEL, ИмяНомерЛиста, СтрокаЗаголовка, НачСтрока, КонСтрока, КолвоСтрокExcel); 21 | КонецПроцедуры 22 | 23 | // Метод "NativeXLSX" (ЧтениеXML). 24 | // Преобразует текст формата XML (файл типа XLSX) в таблицу значений, 25 | // при этом колонки таблицы формируются на основе описания в XML. 26 | // 27 | // Параметры: 28 | // ФайлEXCEL - Полное имя файла (путь к файлу с именем файла и расширением) 29 | // ИмяНомерЛиста - Структура Имя и Номер выбранного листа файла EXCEL. 30 | // СтрокаЗаголовка (по умолчанию = 1) - Номер строки EXCEL, в которой расположены заголовки колонок. 31 | // Не используется. 32 | // В обработке 1-я строка анализируется для сопоставления колонок EXCEL с реквизитами 1С (справочники, докуметны, регистры). 33 | // НачСтрока (по-умолчанию = 0) - Номер начальной строки, начиная с которой считываются данные из EXCEL. 34 | // КонСтрока (по-умолчанию = 0) - Номер конечной строки, которой заканчиваются считываемые данные из EXCEL. 35 | // Если НачСтрока=0 и КонСтрока=0, то считывается вся таблица, находящаяся на листе EXCEL. 36 | // КолвоСтрокExcel - Количество строк на листе "ИмяЛиста" EXCEL. Возвращается в вызываемую процедуру. 37 | // 38 | // Возвращаемые значения: 39 | // ТаблицаРезультат - Результат считывания с листа "ИмяНомерЛиста" EXCEL. 40 | // 41 | &НаСервере 42 | Функция ЗагрузитьМетодом_NativeXLSX(Знач ФайлEXCEL, Знач ИмяНомерЛиста, Знач СтрокаЗаголовка = 1, Знач НачСтрока = 0, Знач КонСтрока = 0, КолвоСтрокExcel = 0) 43 | Перем ZIPКаталог, ФайлИмяЛиста, ФайлНомерЛиста, КолвоКолонокEXCEL, НомерСтроки, НомерКолонки, ИмяКолонки, ИндексКолонки, ШиринаКолонки, ДлинаСтроки; 44 | Перем МассивИменКолонокXLSX, МассивSharedStrings, МассивNumFmtId, СоответствиеNumFmtIdFormatCode; 45 | Перем SheetX,ЗначениеЯчейки, ТипЗначения, ФорматЯчейки, ФорматСтиля; 46 | Перем ТаблицаРезультат, НоваяСтрока; 47 | 48 | ФайлНомерЛиста = ИмяНомерЛиста.НомерЛиста; 49 | ФайлНомерЛиста = ?(ФайлНомерЛиста = 0, 1, ФайлНомерЛиста); 50 | 51 | ZIPКаталог = КаталогВременныхФайлов() + "XLSX\"; 52 | Если НЕ ПредварительнаяОбработкаФайлаXLSX(ФайлEXCEL, ZIPКаталог) Тогда 53 | Возврат Новый ТаблицаЗначений; 54 | КонецЕсли; 55 | 56 | СоответствиеNumFmtIdFormatCode = Новый Соответствие; 57 | МассивNumFmtId = ИзвлечьДанныеИзФайла_StylesXML(ZIPКаталог, СоответствиеNumFmtIdFormatCode); 58 | 59 | МассивSharedStrings = ИзвлечьДанныеИзФайла_SharedStringsXML(ZIPКаталог); 60 | 61 | SheetX = Новый ЧтениеXML; 62 | SheetX.ОткрытьФайл(ZIPКаталог + "XL\WorkSheets\Sheet" + ФайлНомерЛиста + ".xml"); 63 | 64 | МассивИменКолонокXLSX = ПолучитьМассивИменКолонокНаЛистеXLSX(SheetX); 65 | КолвоКолонокEXCEL = МассивИменКолонокXLSX.Количество(); 66 | 67 | // Создание результирующей таблицы, в которую будут записываться считанные из EXCEL данные. 68 | ТаблицаРезультат = Новый ТаблицаЗначений; 69 | // Формирование колонок результирующей таблицы. 70 | // "НомерСтроки" - для наглядности и удобства. 71 | // В зависимости от разрабатываемой обработки. 72 | // "Сопоставлено" - может быть другим. 73 | // Здесь же могут быть добавлены другие колонки, не формируемые из содержимого файла EXCEL. 74 | ТаблицаРезультат.Колонки.Добавить("НомерСтроки", Новый ОписаниеТипов("Число"), "№", 4); 75 | ТаблицаРезультат.Колонки.Добавить("Сопоставлено", Новый ОписаниеТипов("Булево"), "Сопоставлено", 1); 76 | ТаблицаРезультат.Колонки.Добавить("УровеньГруппировки", Новый ОписаниеТипов("Число"), "Гр", 2); // Группировка строк в файле EXCEL. 77 | Для ит = 1 ПО КолвоКолонокExcel Цикл 78 | ИмяКолонки = "N" + ит; 79 | Колонка = ТаблицаРезультат.Колонки.Добавить(ИмяКолонки); 80 | КонецЦикла; 81 | 82 | SheetX = Новый ЧтениеXML; 83 | SheetX.ОткрытьФайл(ZIPКаталог + "XL\WorkSheets\Sheet" + ФайлНомерЛиста + ".xml"); 84 | 85 | ЭтоНачалоДанных = Ложь; 86 | // Считать очередной узел XML. 87 | Пока SheetX.Прочитать() Цикл 88 | Если ВРег(SheetX.Имя) = "SHEETDATA" И SheetX.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда 89 | ЭтоНачалоДанных = Истина; 90 | Прервать; 91 | КонецЕсли; 92 | КонецЦикла; 93 | Если НЕ ЭтоНачалоДанных Тогда 94 | Возврат Новый ТаблицаЗначений; 95 | КонецЕсли; 96 | 97 | // Считать очередной узел XML. 98 | НомерСтроки = 0; 99 | Пока SheetX.Прочитать() Цикл 100 | Если ВРег(SheetX.Имя) = "SHEETDATA" И SheetX.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда 101 | Прервать; // Окончание данных. 102 | КонецЕсли; 103 | Если ВРег(SheetX.Имя) = "ROW" И SheetX.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда 104 | НомерСтроки = НомерСтроки + 1; 105 | Если НЕ НачСтрока = 0 И НЕ НомерСтроки = 1 И НомерСтроки < НачСтрока Тогда 106 | Продолжить; 107 | КонецЕсли; 108 | НоваяСтрока = ТаблицаРезультат.Добавить(); 109 | НоваяСтрока.НомерСтроки = НомерСтроки; 110 | НоваяСтрока.УровеньГруппировки = SheetX.ЗначениеАтрибута("outlineLevel"); 111 | Пока SheetX.Прочитать() Цикл // Считаем колонки строки EXCEL. 112 | Если ВРег(SheetX.Имя) = "ROW" Тогда 113 | Прервать; 114 | КонецЕсли; 115 | Если ВРег(SheetX.Имя) = "SHEETDATA" И SheetX.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда 116 | Прервать; // Окончание данных. 117 | КонецЕсли; 118 | Если ВРег(SheetX.Имя) = "C" И SheetX.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда 119 | ТипЗначения = SheetX.ЗначениеАтрибута("t"); 120 | ФорматЯчейки = SheetX.ЗначениеАтрибута("s"); 121 | ИмяКолонки = SheetX.ЗначениеАтрибута("r"); 122 | ИмяКолонкиБезЦифр = ЗаменитьОдниСимволыДругими("0123456789", ИмяКолонки, ""); 123 | ИндексКолонки = МассивИменКолонокXLSX.Найти(ИмяКолонкиБезЦифр)+1; 124 | SheetX.Прочитать(); 125 | Если ВРег(SheetX.Имя) = "V" ИЛИ ВРег(SheetX.Имя) = "F" Тогда // "V" - Значение, "F" - Формула. 126 | Если ВРег(SheetX.Имя) = "F" Тогда 127 | Пока НЕ ВРег(SheetX.Имя) = "V" Цикл 128 | SheetX.Прочитать(); 129 | КонецЦикла; 130 | КонецЕсли; 131 | SheetX.Прочитать(); 132 | Если ВРег(SheetX.Имя) = "#TEXT" Тогда 133 | ЗначениеЯчейки = SheetX.Значение; 134 | ФорматСтиля = ""; 135 | Если (НЕ ФорматЯчейки = "" И НЕ ФорматЯчейки = Неопределено) Тогда 136 | Попытка 137 | ИндексФормата = Число(ФорматЯчейки); 138 | ФорматСтиля = СоответствиеNumFmtIdFormatCode.Получить(МассивNumFmtId[ИндексФормата]); 139 | Исключение 140 | ФорматСтиля = ""; 141 | КонецПопытки; 142 | КонецЕсли; 143 | Если ЗначениеЗаполнено(ЗначениеЯчейки) Тогда 144 | Если ТипЗначения = Неопределено ИЛИ ВРег(ТипЗначения) = "N" ИЛИ ВРег(ТипЗначения) = "B" Тогда 145 | Попытка 146 | Значение1 = Число(ЗначениеЯчейки); 147 | Исключение 148 | Значение1 = ЗначениеЯчейки; 149 | КонецПопытки; 150 | ЗначениеЯчейки = Значение1; 151 | Если (ФорматСтиля = "" ИЛИ ФорматСтиля = Неопределено) Тогда 152 | // ФорматСтиля = Неопределено - Атрибут "s" отсутствует. 153 | // MS Office (2010) может не формировать в xml-файле описание стиля форматирования для ячейки. 154 | // LibreOffice (4.1.5) формирует в xml-файле необходимые описания стиля форматирования ячейки. 155 | // Сообщить("Не определен стиль форматирования для кода " + ФорматЯчейки + " значения " + ЗначениеЯчейки); 156 | КонецЕсли; 157 | 158 | Если ТипЗнч(ЗначениеЯчейки) = Тип("Строка") 159 | И (Найти(ЗначениеЯчейки, "E-") > 0 ИЛИ Найти(ЗначениеЯчейки, "E+") > 0) Тогда 160 | ЗначениеЯчейки = ПолучитьЧислоВСтепениИзСтроковогоЗначения(ЗначениеЯчейки); 161 | КонецЕсли; 162 | 163 | Если ТипЗнч(ЗначениеЯчейки) = Тип("Число") Тогда 164 | // ПРОЦЕНТ. 165 | Если ЭтоПроцентXLSX(ЗначениеЯчейки, ФорматСтиля) Тогда 166 | ЗначениеЯчейки = Окр(ЗначениеЯчейки * 100, 3); 167 | // БУЛЕВО. 168 | ИначеЕсли ЭтоБулевоXLSX(ЗначениеЯчейки, ФорматСтиля) Тогда 169 | ЗначениеЯчейки = Булево(ЗначениеЯчейки); 170 | // ВРЕМЯ. 171 | ИначеЕсли ЭтоВремяXLSX(ЗначениеЯчейки, ФорматСтиля) Тогда 172 | ЗначениеЯчейки = КонвертироватьЧислоXLSXвДатуВремя(ЗначениеЯчейки); 173 | // ДАТА. 174 | ИначеЕсли ЭтоДатаXLSX(ЗначениеЯчейки, ФорматСтиля) Тогда 175 | ЗначениеЯчейки = КонвертироватьЧислоXLSXвДату(ЗначениеЯчейки); 176 | // ЧИСЛО. 177 | ИначеЕсли ТипЗначения = Неопределено 178 | ИЛИ ( ЭтоЧислоXLSX(ЗначениеЯчейки, ФорматСтиля) 179 | И НЕ ЭтоБулевоXLSX(ЗначениеЯчейки, ФорматСтиля) 180 | И НЕ ЭтоВремяXLSX(ЗначениеЯчейки, ФорматСтиля) 181 | И НЕ ЭтоДатаXLSX(ЗначениеЯчейки, ФорматСтиля) ) 182 | Тогда 183 | // Без преобразования. 184 | Иначе 185 | // Прочие форматы. 186 | КонецЕсли; 187 | 188 | Иначе 189 | 190 | Сообщить("Не удалось преобразовать значение к ""числовому""(процент, время, дата, число) типу."); 191 | 192 | КонецЕсли; 193 | 194 | ИначеЕсли ВРег(ТипЗначения) = "S" Тогда 195 | 196 | // МассивSharedStrings может быть пустым. 197 | Попытка 198 | ЗначениеЯчейки = СокрЛП(МассивSharedStrings[Число(SheetX.Значение)]); 199 | Исключение 200 | ЗначениеЯчейки = ""; 201 | КонецПопытки; 202 | 203 | ИначеЕсли ВРег(ТипЗначения) = "STR" Тогда 204 | 205 | Если ТипЗнч(ЗначениеЯчейки) = Тип("Строка") Тогда 206 | ЗначениеЯчейки = СокрЛП(ЗначениеЯчейки); 207 | КонецЕсли; 208 | 209 | КонецЕсли; 210 | КонецЕсли; 211 | 212 | ИмяКолонки = "N"+ИндексКолонки; 213 | НоваяСтрока[ИмяКолонки] = ЗначениеЯчейки; 214 | // Используется при формировании таблицы на форме обработки. 215 | ШиринаКолонки = ТаблицаРезультат.Колонки[ИмяКолонки].Ширина; 216 | ДлинаСтроки = СтрДлина(СокрЛП(ЗначениеЯчейки)); 217 | ТаблицаРезультат.Колонки[ИмяКолонки].Ширина = ?(ШиринаКолонки < ДлинаСтроки, ДлинаСтроки, ШиринаКолонки); 218 | 219 | КонецЕсли; 220 | КонецЕсли; 221 | КонецЕсли; 222 | КонецЦикла; 223 | Если ((НЕ КонСтрока = 0 И (НомерСтроки + 1) > КонСтрока) 224 | ИЛИ (НЕ КолвоСтрокExcel = 0 И (НомерСтроки + 1) > КолвоСтрокExcel)) Тогда 225 | Прервать; // Окончание диапазона считываемых данных. 226 | КонецЕсли; 227 | КонецЕсли; 228 | КонецЦикла; 229 | 230 | // Завершение работы. 231 | // Закрытие Объектов. 232 | SheetX.Закрыть(); 233 | 234 | УдалитьКолонкиСНулевойШириной(ТаблицаРезультат); 235 | 236 | Возврат ТаблицаРезультат; 237 | 238 | КонецФункции 239 | 240 | &НаСервере 241 | Функция ПредварительнаяОбработкаФайлаXLSX(ФайлEXCEL, ZIPКаталог) 242 | Перем Файл; 243 | 244 | Файл = ПолучитьОбъектФайл(ФайлEXCEL); 245 | Если Файл = Неопределено Тогда 246 | Сообщить("Невозможно загрузить данные, т.к. невозможно открыть для чтения файл: 247 | |" + ФайлEXCEL); 248 | Возврат Ложь; 249 | КонецЕсли; 250 | 251 | Если НЕ ВРег(Файл.Расширение) = ".XLSX" Тогда 252 | Сообщить("Файл с расширением " + Файл.Расширение +" не поддерживается методом NativeXLSX: 253 | |" + ФайлEXCEL); 254 | Возврат Ложь; 255 | КонецЕсли; 256 | 257 | Если НЕ РаспаковатьXLSXвКаталогВременныхФайлов(ФайлEXCEL, ZIPКаталог) Тогда 258 | Сообщить("Ошибка распаковки файла. 259 | |Возможно каталог временных файлов занят. 260 | |" + ФайлEXCEL); 261 | Возврат Ложь; 262 | КонецЕсли; 263 | 264 | Возврат Истина; 265 | 266 | КонецФункции 267 | 268 | &НаСервере 269 | Функция ПолучитьОбъектФайл(Знач ФайлEXCEL) 270 | Перем Файл; 271 | 272 | Если НЕ ЗначениеЗаполнено(ФайлEXCEL) Тогда 273 | Возврат Неопределено; 274 | КонецЕсли; 275 | 276 | Файл = Новый Файл(ФайлEXCEL); 277 | Если НЕ ФайлСуществуетИДоступен(Файл.ПолноеИмя) Тогда 278 | Сообщить("Файл не существует/не доступен: 279 | |" + ФайлEXCEL); 280 | Возврат Неопределено; 281 | КонецЕсли; 282 | 283 | Возврат Файл; 284 | 285 | КонецФункции 286 | 287 | &НаСервере 288 | Функция ФайлСуществуетИДоступен(ПолноеИмяФайла) 289 | Перем Файл; 290 | 291 | Файл = Новый Файл(ПолноеИмяФайла); 292 | Если НЕ Файл.Существует() Тогда 293 | Возврат Ложь; 294 | КонецЕсли; 295 | 296 | // Проверка: Занят ли файл другим процессом? 297 | Если НЕ ВРег(Файл.Расширение) = ".DBF" Тогда 298 | Попытка 299 | ПереместитьФайл(Файл.ПолноеИмя,Файл.ПолноеИмя); 300 | Исключение 301 | Сообщить("Файл не доступен: 302 | |" + Файл.ПолноеИмя); 303 | Возврат Ложь; 304 | КонецПопытки; 305 | КонецЕсли; 306 | 307 | Возврат Истина; 308 | 309 | КонецФункции 310 | 311 | &НаСервере 312 | Функция РаспаковатьXLSXвКаталогВременныхФайлов(ФайлEXCEL, ZIPКаталог) 313 | Перем ZIPФайл; 314 | 315 | Попытка 316 | УдалитьФайлы(ZIPКаталог); 317 | 318 | ZIPФайл = Новый ЧтениеZipФайла; 319 | ZIPФайл.Открыть(ФайлEXCEL); 320 | ZIPФайл.ИзвлечьВсе(ZIPКаталог, РежимВосстановленияПутейФайловZIP.Восстанавливать); 321 | Возврат Истина; 322 | Исключение 323 | Возврат Ложь; 324 | КонецПопытки; 325 | 326 | Возврат Истина; 327 | 328 | КонецФункции 329 | 330 | &НаСервере 331 | Функция ИзвлечьДанныеИзФайла_StylesXML(ZIPКаталог, СоответствиеNumFmtIdFormatCode) 332 | Перем Файл, Styles; 333 | Перем МассивNumFmtId, ит; 334 | 335 | МассивNumFmtId = Новый Массив; 336 | СоответствиеNumFmtIdFormatCode = Новый Соответствие; 337 | 338 | Файл = Новый Файл(ZIPКаталог + "XL\Styles.xml"); 339 | Если НЕ Файл.Существует() Тогда 340 | Возврат МассивNumFmtId; 341 | КонецЕсли; 342 | 343 | Styles = Новый ЧтениеXML; 344 | Styles.ОткрытьФайл(Файл.ПолноеИмя); 345 | 346 | Пока Styles.Прочитать() Цикл 347 | Если ВРег(Styles.Имя) = ВРег("numFmt") И Styles.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда 348 | СоответствиеNumFmtIdFormatCode.Вставить(Styles.ЗначениеАтрибута("numFmtId"), ВРег(Styles.ЗначениеАтрибута("formatCode"))); 349 | КонецЕсли; 350 | Если ВРег(Styles.Имя) = ВРег("cellXfs") Тогда 351 | Пока Styles.Прочитать() Цикл 352 | Если ВРег(Styles.Имя) = ВРег("xf") И Styles.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда 353 | МассивNumFmtId.Добавить(Styles.ЗначениеАтрибута("numFmtId")); 354 | КонецЕсли; 355 | КонецЦикла; 356 | КонецЕсли; 357 | КонецЦикла; 358 | 359 | // Завершение работы. 360 | // Закрытие Объектов. 361 | Styles.Закрыть(); 362 | 363 | // Проверка сопоставления кодов массива и соответствия. 364 | // MS Office может не формировать в xml-файле описание стиля форматирования для ячейки. 365 | // LibreOffice формирует в xml-файле необходимые описания стиля форматирования ячейки. 366 | Для Каждого ит ИЗ МассивNumFmtId Цикл 367 | Если СоответствиеNumFmtIdFormatCode.Получить(ит) = Неопределено Тогда 368 | Если ит = "0" Тогда // Стандарт для числа (Целое число). 369 | СоответствиеNumFmtIdFormatCode.Вставить(ит, "GENERAL"); 370 | ИначеЕсли ит = "9" ИЛИ ит = "10" Тогда // Форматы для % ("0%", "0.00%"). 371 | СоответствиеNumFmtIdFormatCode.Вставить(ит, "0%"); 372 | ИначеЕсли ит = "14" ИЛИ ит = "16" Тогда // Форматы для даты. 373 | СоответствиеNumFmtIdFormatCode.Вставить(ит, "DD.MM.YYYY"); 374 | ИначеЕсли ит = "45" ИЛИ ит = "46" ИЛИ ит = "47" Тогда // Форматы для времени. 375 | СоответствиеNumFmtIdFormatCode.Вставить(ит, "HH:MM:SS"); 376 | КонецЕсли; 377 | КонецЕсли; 378 | КонецЦикла; 379 | 380 | Возврат МассивNumFmtId; 381 | 382 | КонецФункции 383 | 384 | &НаСервере 385 | Функция ИзвлечьДанныеИзФайла_SharedStringsXML(ZIPКаталог) 386 | Перем Файл, SharedStrings; 387 | Перем МассивSharedStrings; 388 | 389 | // Если в файле EXCEL не содержится значений, имеющих тип "СТРОКА", то файл "SharedStrings.xml" не формируется. 390 | 391 | МассивSharedStrings = Новый Массив; 392 | 393 | Файл = Новый Файл(ZIPКаталог + "XL\SharedStrings.xml"); 394 | Если НЕ Файл.Существует() Тогда 395 | Возврат МассивSharedStrings; 396 | КонецЕсли; 397 | 398 | SharedStrings = Новый ЧтениеXML; 399 | SharedStrings.ОткрытьФайл(Файл.ПолноеИмя); 400 | 401 | ФлагСтрокаЗаписана = Ложь; 402 | 403 | Пока SharedStrings.Прочитать() Цикл 404 | Если ВРег(SharedStrings.Имя) = "SI" и SharedStrings.ТипУзла = ТипУзлаXML.НачалоЭлемента тогда 405 | ФлагСтрокаЗаписана = Ложь; 406 | КонецЕсли; 407 | 408 | Если ВРег(SharedStrings.Имя) = "#TEXT" Тогда 409 | МассивSharedStrings.Добавить(SharedStrings.Значение); 410 | ФлагСтрокаЗаписана = Истина; 411 | КонецЕсли; 412 | 413 | Если ВРег(SharedStrings.Имя) = "SI" и SharedStrings.ТипУзла = ТипУзлаXML.КонецЭлемента и не ФлагСтрокаЗаписана тогда 414 | //встретили пустую строку! 415 | МассивSharedStrings.Добавить(""); 416 | КонецЕсли; 417 | 418 | КонецЦикла; 419 | 420 | // Завершение работы. 421 | // Закрытие Объектов. 422 | SharedStrings.Закрыть(); 423 | 424 | Возврат МассивSharedStrings; 425 | 426 | КонецФункции 427 | 428 | &НаСервере 429 | Функция ПолучитьМассивИменКолонокНаЛистеXLSX(SheetX) 430 | Перем ДиапазонДанных, ДиапазонКолонок, ПерваяКолонка, ПоследняяКолонка, НомерПервойК, НомерПоследнейК; 431 | Перем Подсчет, ИмяКолонки; 432 | Перем МассивИменКолонокXLSX, КолвоКолонокEXCEL; 433 | 434 | МассивИменКолонокXLSX = Новый Массив; 435 | 436 | Подсчет = Ложь; 437 | // Считать очередной узел XML. 438 | Пока SheetX.Прочитать() Цикл 439 | // DIMENSION. 440 | Если ВРег(SheetX.Имя) = "DIMENSION" И SheetX.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда 441 | ДиапазонДанных = SheetX.ПолучитьАтрибут("ref"); 442 | ДиапазонКолонок = ЗаменитьОдниСимволыДругими("0123456789", ДиапазонДанных, ""); 443 | ПерваяКолонка = Лев(ДиапазонКолонок, Найти(ДиапазонКолонок ,":") - 1); 444 | ПоследняяКолонка= Сред(ДиапазонКолонок, Найти(ДиапазонКолонок ,":") + 1); 445 | НомерПервойК = НомерКолонкиДесятичный(ПерваяКолонка); 446 | НомерПоследнейК = НомерКолонкиДесятичный(ПоследняяКолонка); 447 | КонецЕсли; 448 | // Подсчет по 1-ой строке. 449 | Если ВРег(SheetX.Имя) = "ROW" Тогда 450 | Если SheetX.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда 451 | // Начало отсчета. 452 | Подсчет = Истина; 453 | ИначеЕсли SheetX.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда 454 | // Окончание отсчета. 455 | Прервать; 456 | КонецЕсли; 457 | КонецЕсли; 458 | Если Подсчет И ВРег(SheetX.Имя) = "C" И SheetX.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда 459 | ИмяКолонки = SheetX.ПолучитьАтрибут("r"); 460 | ИмяКолонки = ЗаменитьОдниСимволыДругими("0123456789", ИмяКолонки, ""); 461 | МассивИменКолонокXLSX.Добавить(ИмяКолонки); 462 | КонецЕсли; 463 | КонецЦикла; 464 | 465 | КолвоКолонокEXCEL = МассивИменКолонокXLSX.Количество(); 466 | Если НЕ НомерПоследнейК = Неопределено Тогда 467 | Если КолвоКолонокEXCEL < НомерПоследнейК Тогда 468 | //СУУ_ЕНС 27 11 17. в контексте текущей задачи лишние сообщения ни к чему, если и так все работает нормально 469 | //Сообщить("Строка заголовков колонок (1-я строка) заполнена не полностью: 470 | //|К-во колонок строки меньше объявленной: " + КолвоКолонокEXCEL + "<" + НомерПоследнейК); 471 | ДополнитьМассивИменКолонокXLSX(НомерПоследнейК, МассивИменКолонокXLSX); 472 | ИначеЕсли КолвоКолонокEXCEL > НомерПоследнейК Тогда 473 | //СУУ_ЕНС 27 11 17. в контексте текущей задачи лишние сообщения ни к чему, если и так все работает нормально 474 | //Сообщить("Строка заголовков колонок (1-я строка) содержит больше колонок, чем объявлено: 475 | //|К-во колонок строки больше объявленной:" + КолвоКолонокEXCEL + ">" + НомерПоследнейК); 476 | КонецЕсли; 477 | КонецЕсли; 478 | 479 | Возврат МассивИменКолонокXLSX; 480 | 481 | КонецФункции 482 | 483 | &НаСервере 484 | Функция НомерКолонкиДесятичный(ИмяКолонкиXLSX) 485 | Перем Латиница, ДлинаНомера, Поз, ит; 486 | Перем НомерКолонки; 487 | 488 | Латиница = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // 26. 489 | ДлинаНомера = СтрДлина(ИмяКолонкиXLSX); 490 | НомерКолонки = 0; 491 | Для ит = 1 ПО ДлинаНомера Цикл 492 | Поз = Найти(Латиница, Сред(ИмяКолонкиXLSX, (ДлинаНомера + 1 - ит), 1)); 493 | НомерКолонки = НомерКолонки + Поз * Pow(26, ит - 1); 494 | КонецЦикла; 495 | 496 | Возврат НомерКолонки; 497 | 498 | КонецФункции 499 | 500 | &НаСервере 501 | Процедура ДополнитьМассивИменКолонокXLSX(Знач КолвоКолонокExcel, МассивИменКолонокXLSX, Индекс = - 1) 502 | Перем Алфавит, ит, Буква; 503 | 504 | Алфавит = РазложитьСтрокуВМассивПодстрок("A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z", ","); 505 | 506 | Если МассивИменКолонокXLSX.Количество() >= КолвоКолонокExcel Тогда 507 | Возврат; 508 | КонецЕсли; 509 | 510 | Если Индекс > Алфавит.Количество() - 1 Тогда 511 | Возврат; 512 | КонецЕсли; 513 | 514 | Буква = ?(Индекс = -1, "", Алфавит[Индекс]); 515 | Для ит = 0 ПО Алфавит.Количество() - 1 Цикл 516 | Если МассивИменКолонокXLSX.Найти(Буква + Алфавит[ит]) = Неопределено Тогда 517 | МассивИменКолонокXLSX.Добавить(Буква + Алфавит[ит]); 518 | КонецЕсли; 519 | Если МассивИменКолонокXLSX.Количество() >= КолвоКолонокExcel Тогда 520 | Возврат; 521 | КонецЕсли; 522 | КонецЦикла; 523 | 524 | Если МассивИменКолонокXLSX.Количество() > КолвоКолонокExcel Тогда 525 | Возврат; 526 | Иначе 527 | Индекс = Индекс + 1; 528 | ДополнитьМассивИменКолонокXLSX(КолвоКолонокExcel, МассивИменКолонокXLSX, Индекс); 529 | КонецЕсли; 530 | 531 | Возврат; 532 | 533 | КонецПроцедуры 534 | 535 | // Функция "расщепляет" строку на подстроки, используя заданный 536 | // разделитель. Разделитель может иметь любую длину. 537 | // Если в качестве разделителя задан пробел, рядом стоящие пробелы 538 | // считаются одним разделителем, а ведущие и хвостовые пробелы параметра Стр 539 | // игнорируются. 540 | // Например, 541 | // РазложитьСтрокуВМассивПодстрок(",один,,,два", ",") возвратит массив значений из пяти элементов, 542 | // три из которых - пустые строки, а 543 | // РазложитьСтрокуВМассивПодстрок(" один два", " ") возвратит массив значений из двух элементов 544 | // 545 | // Параметры: 546 | // Стр - строка, которую необходимо разложить на подстроки. 547 | // Параметр передается по значению. 548 | // Разделитель - строка-разделитель, по умолчанию - запятая. 549 | // 550 | // Возвращаемое значение: 551 | // массив значений, элементы которого - подстроки 552 | // 553 | &НаСервере 554 | Функция РазложитьСтрокуВМассивПодстрок(Знач Стр, Разделитель = ",") 555 | 556 | МассивСтрок = Новый Массив(); 557 | Если Разделитель = " " Тогда 558 | Стр = СокрЛП(Стр); 559 | Пока 1 = 1 Цикл 560 | Поз = Найти(Стр, Разделитель); 561 | Если Поз = 0 Тогда 562 | МассивСтрок.Добавить(СокрЛП(Стр)); 563 | Возврат МассивСтрок; 564 | КонецЕсли; 565 | МассивСтрок.Добавить(СокрЛП(Лев(Стр, Поз - 1))); 566 | Стр = СокрЛ(Сред(Стр, Поз)); 567 | КонецЦикла; 568 | Иначе 569 | ДлинаРазделителя = СтрДлина(Разделитель); 570 | Пока 1 = 1 Цикл 571 | Поз = Найти(Стр, Разделитель); 572 | Если Поз = 0 Тогда 573 | Если (СокрЛП(Стр) <> "") Тогда 574 | МассивСтрок.Добавить(СокрЛП(Стр)); 575 | КонецЕсли; 576 | Возврат МассивСтрок; 577 | КонецЕсли; 578 | МассивСтрок.Добавить(СокрЛП(Лев(Стр,Поз - 1))); 579 | Стр = Сред(Стр, Поз + ДлинаРазделителя); 580 | КонецЦикла; 581 | КонецЕсли; 582 | 583 | КонецФункции 584 | 585 | &НаСервере 586 | Функция ЭтоЧислоXLSX(Знач ЗначениеЯчейки, Знач ФорматСтиля) 587 | 588 | Если ( ВРег(ФорматСтиля) = "GENERAL" 589 | ИЛИ ВРег(ФорматСтиля) = "STANDARD" 590 | ИЛИ Найти(ФорматСтиля, "0") > 0 ) 591 | Тогда 592 | Возврат Истина; 593 | КонецЕсли; 594 | 595 | Возврат Ложь; 596 | 597 | КонецФункции 598 | 599 | &НаСервере 600 | Функция ЭтоПроцентXLSX(Знач ЗначениеЯчейки, Знач ФорматСтиля) 601 | 602 | Если ( Найти(ФорматСтиля, "%") > 0 ) 603 | Тогда 604 | Возврат Истина; 605 | КонецЕсли; 606 | 607 | Возврат Ложь; 608 | 609 | КонецФункции 610 | 611 | &НаСервере 612 | Функция ЭтоБулевоXLSX(ЗначениеЯчейки, ФорматСтиля) 613 | 614 | Если (ЗначениеЯчейки = 0 ИЛИ ЗначениеЯчейки = 1) 615 | И Найти(ВРег(ФорматСтиля), "ИСТИНА") > 0 ИЛИ Найти(ВРег(ФорматСтиля), "ЛОЖЬ") > 0 616 | ИЛИ Найти(ВРег(ФорматСтиля), "TRUE") > 0 ИЛИ Найти(ВРег(ФорматСтиля), "FALSE") > 0 617 | Тогда 618 | Возврат Истина; 619 | КонецЕсли; 620 | 621 | Возврат Ложь; 622 | 623 | КонецФункции 624 | 625 | &НаСервере 626 | Функция ЭтоДатаXLSX(Знач ЗначениеЯчейки, Знач ФорматСтиля) 627 | 628 | Если ЗначениеЯчейки = Цел(ЗначениеЯчейки) И 629 | ( Найти(ФорматСтиля, "DD") > 0 630 | ИЛИ Найти(ФорматСтиля, "MM") > 0 631 | ИЛИ Найти(ФорматСтиля, "YY") > 0 632 | ИЛИ Найти(ФорматСтиля, "QQ") > 0 633 | ИЛИ Найти(ФорматСтиля, "WW") > 0 ) 634 | Тогда 635 | Возврат Истина; 636 | КонецЕсли; 637 | 638 | Возврат Ложь; 639 | 640 | КонецФункции 641 | 642 | &НаСервере 643 | Функция ЭтоВремяXLSX(Знач ЗначениеЯчейки, Знач ФорматСтиля) 644 | 645 | Если ЗначениеЯчейки < 1 И 646 | ( Найти(ФорматСтиля, "HH:") > 0 647 | ИЛИ Найти(ФорматСтиля, "[HH]:") > 0 648 | ИЛИ Найти(ФорматСтиля, "[H]:") > 0 649 | ИЛИ Найти(ФорматСтиля, "MM:") > 0 650 | ИЛИ Найти(ФорматСтиля, ":SS") > 0 ) 651 | Тогда 652 | Возврат Истина; 653 | КонецЕсли; 654 | 655 | Возврат Ложь; 656 | 657 | КонецФункции 658 | 659 | &НаСервере 660 | Функция КонвертироватьЧислоXLSXвДату(Знач Число) 661 | Перем Дата1900, Разница, ДатаРезультат; 662 | 663 | Дата1900 = Дата("19000101"); 664 | 665 | Разница = Число - 2; // EXCEL ошибочно считает 1900-й год високосным. 666 | Разница = ?(Разница < 0, 0, Разница); 667 | 668 | ДатаРезультат = Дата1900 + Разница * 24 * 60 * 60; 669 | 670 | Возврат ДатаРезультат; 671 | 672 | КонецФункции 673 | 674 | &НаСервере 675 | Функция КонвертироватьЧислоXLSXвДатуВремя(Знач Число) 676 | Перем КВоСекунд; 677 | Перем ВремяРезультат; 678 | 679 | // 0,0000115740740740741 = 1 сек. 680 | // 1 = 24 часа 00 мин 00 сек. 681 | 682 | Если ТипЗнч(Число) = Тип("Число") Тогда 683 | КВоСекунд = Число * 100000 / 1.15740740740741; 684 | КВоСекунд = Окр(КВоСекунд); 685 | Иначе 686 | Сообщить("Ошибка определения значения типа ""Время""."); 687 | КонецЕсли; 688 | 689 | ВремяРезультат = Дата("19000101000000") + КВоСекунд; 690 | 691 | Возврат ВремяРезультат; 692 | 693 | КонецФункции 694 | 695 | &НаСервере 696 | Функция ПолучитьЧислоВСтепениИзСтроковогоЗначения(Знач ЗначениеЯчейки) 697 | Перем Поз1Е, Степень; 698 | Перем Значение; 699 | 700 | Если Найти(ЗначениеЯчейки, "E-") > 0 Тогда 701 | Поз1Е = Найти(ЗначениеЯчейки, "E-"); 702 | Степень = Сред(ЗначениеЯчейки, Поз1Е+2); 703 | Значение = Лев(ЗначениеЯчейки, Поз1Е-1); 704 | Попытка 705 | Степень = Число(Степень); 706 | Значение = Число(Значение) / Pow(10, Степень); 707 | Исключение 708 | Значение = ЗначениеЯчейки; 709 | КонецПопытки; 710 | ИначеЕсли Найти(ЗначениеЯчейки, "E+") > 0 Тогда 711 | Поз1Е = Найти(ЗначениеЯчейки, "E+"); 712 | Степень = Сред(ЗначениеЯчейки, Поз1Е+2); 713 | Значение = Лев(ЗначениеЯчейки, Поз1Е-1); 714 | Попытка 715 | Степень = Число(Степень); 716 | Значение = Число(Значение) * Pow(10, Степень); 717 | Исключение 718 | Значение = ЗначениеЯчейки; 719 | КонецПопытки; 720 | Иначе 721 | Значение = ЗначениеЯчейки; 722 | КонецЕсли; 723 | 724 | Возврат Значение; 725 | 726 | КонецФункции 727 | 728 | &НаСервере 729 | Функция ЗаменитьОдниСимволыДругими(ЗаменяемыеСимволы, Строка, СимволыЗамены) 730 | Результат = Строка; 731 | Для НомерСимвола = 1 По СтрДлина(ЗаменяемыеСимволы) Цикл 732 | Результат = СтрЗаменить(Результат, Сред(ЗаменяемыеСимволы, НомерСимвола, 1), Сред(СимволыЗамены, НомерСимвола, 1)); 733 | КонецЦикла; 734 | Возврат Результат; 735 | КонецФункции 736 | 737 | &НаСервере 738 | Процедура УдалитьКолонкиСНулевойШириной(ТаблицаРезультат) 739 | Перем МассивПустыхКолонок; 740 | // Найдем пустые колонки. 741 | МассивПустыхКолонок = Новый Массив; 742 | Для Каждого Колонка ИЗ ТаблицаРезультат.Колонки Цикл 743 | Если Колонка.Ширина = 0 Тогда 744 | МассивПустыхКолонок.Добавить(Колонка.Имя); 745 | КонецЕсли; 746 | КонецЦикла; 747 | // Удалим пустые колонки. 748 | Для Каждого ПустаяКолонка ИЗ МассивПустыхКолонок Цикл 749 | ТаблицаРезультат.Колонки.Удалить(ПустаяКолонка); 750 | КонецЦикла; 751 | КонецПроцедуры 752 | -------------------------------------------------------------------------------- /src/ReadXLSX/ЧтениеXLSXбезВК/und/18528942-b13d-4756-a1e1-a7951fb20d18.0: -------------------------------------------------------------------------------- 1 | {2, 2 | {28,0,0,0,0,1,0,0,00000000-0000-0000-0000-000000000000,1, 3 | {1,0},0,0,1,1,1,0,1,0, 4 | {0}, 5 | {0},1, 6 | {17, 7 | {-1,02023637-7868-4a5f-8576-835a76e0c9ba},0,0,1, 8 | {0, 9 | {0, 10 | {"B",1},0} 11 | },9,"ФормаКоманднаяПанель", 12 | {1,0}, 13 | {1,0},0,1,0,0,0,2,2, 14 | {3,4, 15 | {0} 16 | }, 17 | {6,3,0,1}, 18 | {0,0,0},1, 19 | {0,0,1},1,a9f3b1ac-f51b-431e-b102-55a69acdecad, 20 | {19, 21 | {1,02023637-7868-4a5f-8576-835a76e0c9ba},0,1, 22 | {0, 23 | {0, 24 | {"B",1},0} 25 | },0,"ФормаПрочитатьXLSX", 26 | {1,0},1, 27 | {1,409b9a53-7f7e-4178-86c1-33176c7c7a7a}, 28 | {0},3,0,0,0,2,2,0,0,0, 29 | {3,4, 30 | {0} 31 | }, 32 | {3,4, 33 | {0} 34 | }, 35 | {3,4, 36 | {0} 37 | }, 38 | {6,3,0,1}, 39 | {0,0,0},0, 40 | {3,0, 41 | {0},"",-1,-1,1,0},1, 42 | {"Pattern"},"",2},1},0,"","",1, 43 | {17, 44 | {0},0,0,0,7,"Navigator", 45 | {1,0}, 46 | {1,0},0,1,0,0,0,2,2, 47 | {3,4, 48 | {0} 49 | }, 50 | {6,3,0,1}, 51 | {0,0,0},0,0,1} 52 | }," 53 | &НаКлиенте 54 | Процедура ПрочитатьXLSX(Команда) 55 | ФайлEXCEL= ""c:\techjourn\micex.xlsx""; 56 | ИмяНомерЛиста = Новый Структура (""ИмяЛиста, НомерЛиста"",""Лист1"", 1); 57 | СтрокаЗаголовка = 1; 58 | НачСтрока = 0; 59 | КонСтрока = 0; 60 | КолвоСтрокExcel = 0; 61 | ЗагрузитьМетодом_NativeXLSX_НаСервере(ФайлEXCEL, ИмяНомерЛиста, СтрокаЗаголовка, НачСтрока, КонСтрока, КолвоСтрокExcel); 62 | КонецПроцедуры 63 | 64 | 65 | //https://infostart.ru/public/225624/ 66 | 67 | 68 | 69 | &НаСервере 70 | Процедура ЗагрузитьМетодом_NativeXLSX_НаСервере(ФайлEXCEL, ИмяНомерЛиста, СтрокаЗаголовка, НачСтрока, КонСтрока, КолвоСтрокExcel) 71 | ТаблицаРезультат = ЗагрузитьМетодом_NativeXLSX(ФайлEXCEL, ИмяНомерЛиста, СтрокаЗаголовка, НачСтрока, КонСтрока, КолвоСтрокExcel); 72 | КонецПроцедуры 73 | 74 | // Метод ""NativeXLSX"" (ЧтениеXML). 75 | // Преобразует текст формата XML (файл типа XLSX) в таблицу значений, 76 | // при этом колонки таблицы формируются на основе описания в XML. 77 | // 78 | // Параметры: 79 | // ФайлEXCEL - Полное имя файла (путь к файлу с именем файла и расширением) 80 | // ИмяНомерЛиста - Структура Имя и Номер выбранного листа файла EXCEL. 81 | // СтрокаЗаголовка (по умолчанию = 1) - Номер строки EXCEL, в которой расположены заголовки колонок. 82 | // Не используется. 83 | // В обработке 1-я строка анализируется для сопоставления колонок EXCEL с реквизитами 1С (справочники, докуметны, регистры). 84 | // НачСтрока (по-умолчанию = 0) - Номер начальной строки, начиная с которой считываются данные из EXCEL. 85 | // КонСтрока (по-умолчанию = 0) - Номер конечной строки, которой заканчиваются считываемые данные из EXCEL. 86 | // Если НачСтрока=0 и КонСтрока=0, то считывается вся таблица, находящаяся на листе EXCEL. 87 | // КолвоСтрокExcel - Количество строк на листе ""ИмяЛиста"" EXCEL. Возвращается в вызываемую процедуру. 88 | // 89 | // Возвращаемые значения: 90 | // ТаблицаРезультат - Результат считывания с листа ""ИмяНомерЛиста"" EXCEL. 91 | // 92 | &НаСервере 93 | Функция ЗагрузитьМетодом_NativeXLSX(Знач ФайлEXCEL, Знач ИмяНомерЛиста, Знач СтрокаЗаголовка = 1, Знач НачСтрока = 0, Знач КонСтрока = 0, КолвоСтрокExcel = 0) 94 | Перем ZIPКаталог, ФайлИмяЛиста, ФайлНомерЛиста, КолвоКолонокEXCEL, НомерСтроки, НомерКолонки, ИмяКолонки, ИндексКолонки, ШиринаКолонки, ДлинаСтроки; 95 | Перем МассивИменКолонокXLSX, МассивSharedStrings, МассивNumFmtId, СоответствиеNumFmtIdFormatCode; 96 | Перем SheetX,ЗначениеЯчейки, ТипЗначения, ФорматЯчейки, ФорматСтиля; 97 | Перем ТаблицаРезультат, НоваяСтрока; 98 | 99 | ФайлНомерЛиста = ИмяНомерЛиста.НомерЛиста; 100 | ФайлНомерЛиста = ?(ФайлНомерЛиста = 0, 1, ФайлНомерЛиста); 101 | 102 | ZIPКаталог = КаталогВременныхФайлов() + ""XLSX\""; 103 | Если НЕ ПредварительнаяОбработкаФайлаXLSX(ФайлEXCEL, ZIPКаталог) Тогда 104 | Возврат Новый ТаблицаЗначений; 105 | КонецЕсли; 106 | 107 | СоответствиеNumFmtIdFormatCode = Новый Соответствие; 108 | МассивNumFmtId = ИзвлечьДанныеИзФайла_StylesXML(ZIPКаталог, СоответствиеNumFmtIdFormatCode); 109 | 110 | МассивSharedStrings = ИзвлечьДанныеИзФайла_SharedStringsXML(ZIPКаталог); 111 | 112 | SheetX = Новый ЧтениеXML; 113 | SheetX.ОткрытьФайл(ZIPКаталог + ""XL\WorkSheets\Sheet"" + ФайлНомерЛиста + "".xml""); 114 | 115 | МассивИменКолонокXLSX = ПолучитьМассивИменКолонокНаЛистеXLSX(SheetX); 116 | КолвоКолонокEXCEL = МассивИменКолонокXLSX.Количество(); 117 | 118 | // Создание результирующей таблицы, в которую будут записываться считанные из EXCEL данные. 119 | ТаблицаРезультат = Новый ТаблицаЗначений; 120 | // Формирование колонок результирующей таблицы. 121 | // ""НомерСтроки"" - для наглядности и удобства. 122 | // В зависимости от разрабатываемой обработки. 123 | // ""Сопоставлено"" - может быть другим. 124 | // Здесь же могут быть добавлены другие колонки, не формируемые из содержимого файла EXCEL. 125 | ТаблицаРезультат.Колонки.Добавить(""НомерСтроки"", Новый ОписаниеТипов(""Число""), ""№"", 4); 126 | ТаблицаРезультат.Колонки.Добавить(""Сопоставлено"", Новый ОписаниеТипов(""Булево""), ""Сопоставлено"", 1); 127 | ТаблицаРезультат.Колонки.Добавить(""УровеньГруппировки"", Новый ОписаниеТипов(""Число""), ""Гр"", 2); // Группировка строк в файле EXCEL. 128 | Для ит = 1 ПО КолвоКолонокExcel Цикл 129 | ИмяКолонки = ""N"" + ит; 130 | Колонка = ТаблицаРезультат.Колонки.Добавить(ИмяКолонки); 131 | КонецЦикла; 132 | 133 | SheetX = Новый ЧтениеXML; 134 | SheetX.ОткрытьФайл(ZIPКаталог + ""XL\WorkSheets\Sheet"" + ФайлНомерЛиста + "".xml""); 135 | 136 | ЭтоНачалоДанных = Ложь; 137 | // Считать очередной узел XML. 138 | Пока SheetX.Прочитать() Цикл 139 | Если ВРег(SheetX.Имя) = ""SHEETDATA"" И SheetX.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда 140 | ЭтоНачалоДанных = Истина; 141 | Прервать; 142 | КонецЕсли; 143 | КонецЦикла; 144 | Если НЕ ЭтоНачалоДанных Тогда 145 | Возврат Новый ТаблицаЗначений; 146 | КонецЕсли; 147 | 148 | // Считать очередной узел XML. 149 | НомерСтроки = 0; 150 | Пока SheetX.Прочитать() Цикл 151 | Если ВРег(SheetX.Имя) = ""SHEETDATA"" И SheetX.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда 152 | Прервать; // Окончание данных. 153 | КонецЕсли; 154 | Если ВРег(SheetX.Имя) = ""ROW"" И SheetX.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда 155 | НомерСтроки = НомерСтроки + 1; 156 | Если НЕ НачСтрока = 0 И НЕ НомерСтроки = 1 И НомерСтроки < НачСтрока Тогда 157 | Продолжить; 158 | КонецЕсли; 159 | НоваяСтрока = ТаблицаРезультат.Добавить(); 160 | НоваяСтрока.НомерСтроки = НомерСтроки; 161 | НоваяСтрока.УровеньГруппировки = SheetX.ЗначениеАтрибута(""outlineLevel""); 162 | Пока SheetX.Прочитать() Цикл // Считаем колонки строки EXCEL. 163 | Если ВРег(SheetX.Имя) = ""ROW"" Тогда 164 | Прервать; 165 | КонецЕсли; 166 | Если ВРег(SheetX.Имя) = ""SHEETDATA"" И SheetX.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда 167 | Прервать; // Окончание данных. 168 | КонецЕсли; 169 | Если ВРег(SheetX.Имя) = ""C"" И SheetX.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда 170 | ТипЗначения = SheetX.ЗначениеАтрибута(""t""); 171 | ФорматЯчейки = SheetX.ЗначениеАтрибута(""s""); 172 | ИмяКолонки = SheetX.ЗначениеАтрибута(""r""); 173 | ИмяКолонкиБезЦифр = ЗаменитьОдниСимволыДругими(""0123456789"", ИмяКолонки, """"); 174 | ИндексКолонки = МассивИменКолонокXLSX.Найти(ИмяКолонкиБезЦифр)+1; 175 | SheetX.Прочитать(); 176 | Если ВРег(SheetX.Имя) = ""V"" ИЛИ ВРег(SheetX.Имя) = ""F"" Тогда // ""V"" - Значение, ""F"" - Формула. 177 | Если ВРег(SheetX.Имя) = ""F"" Тогда 178 | Пока НЕ ВРег(SheetX.Имя) = ""V"" Цикл 179 | SheetX.Прочитать(); 180 | КонецЦикла; 181 | КонецЕсли; 182 | SheetX.Прочитать(); 183 | Если ВРег(SheetX.Имя) = ""#TEXT"" Тогда 184 | ЗначениеЯчейки = SheetX.Значение; 185 | ФорматСтиля = """"; 186 | Если (НЕ ФорматЯчейки = """" И НЕ ФорматЯчейки = Неопределено) Тогда 187 | Попытка 188 | ИндексФормата = Число(ФорматЯчейки); 189 | ФорматСтиля = СоответствиеNumFmtIdFormatCode.Получить(МассивNumFmtId[ИндексФормата]); 190 | Исключение 191 | ФорматСтиля = """"; 192 | КонецПопытки; 193 | КонецЕсли; 194 | Если ЗначениеЗаполнено(ЗначениеЯчейки) Тогда 195 | Если ТипЗначения = Неопределено ИЛИ ВРег(ТипЗначения) = ""N"" ИЛИ ВРег(ТипЗначения) = ""B"" Тогда 196 | Попытка 197 | Значение1 = Число(ЗначениеЯчейки); 198 | Исключение 199 | Значение1 = ЗначениеЯчейки; 200 | КонецПопытки; 201 | ЗначениеЯчейки = Значение1; 202 | Если (ФорматСтиля = """" ИЛИ ФорматСтиля = Неопределено) Тогда 203 | // ФорматСтиля = Неопределено - Атрибут ""s"" отсутствует. 204 | // MS Office (2010) может не формировать в xml-файле описание стиля форматирования для ячейки. 205 | // LibreOffice (4.1.5) формирует в xml-файле необходимые описания стиля форматирования ячейки. 206 | // Сообщить(""Не определен стиль форматирования для кода "" + ФорматЯчейки + "" значения "" + ЗначениеЯчейки); 207 | КонецЕсли; 208 | 209 | Если ТипЗнч(ЗначениеЯчейки) = Тип(""Строка"") 210 | И (Найти(ЗначениеЯчейки, ""E-"") > 0 ИЛИ Найти(ЗначениеЯчейки, ""E+"") > 0) Тогда 211 | ЗначениеЯчейки = ПолучитьЧислоВСтепениИзСтроковогоЗначения(ЗначениеЯчейки); 212 | КонецЕсли; 213 | 214 | Если ТипЗнч(ЗначениеЯчейки) = Тип(""Число"") Тогда 215 | // ПРОЦЕНТ. 216 | Если ЭтоПроцентXLSX(ЗначениеЯчейки, ФорматСтиля) Тогда 217 | ЗначениеЯчейки = Окр(ЗначениеЯчейки * 100, 3); 218 | // БУЛЕВО. 219 | ИначеЕсли ЭтоБулевоXLSX(ЗначениеЯчейки, ФорматСтиля) Тогда 220 | ЗначениеЯчейки = Булево(ЗначениеЯчейки); 221 | // ВРЕМЯ. 222 | ИначеЕсли ЭтоВремяXLSX(ЗначениеЯчейки, ФорматСтиля) Тогда 223 | ЗначениеЯчейки = КонвертироватьЧислоXLSXвДатуВремя(ЗначениеЯчейки); 224 | // ДАТА. 225 | ИначеЕсли ЭтоДатаXLSX(ЗначениеЯчейки, ФорматСтиля) Тогда 226 | ЗначениеЯчейки = КонвертироватьЧислоXLSXвДату(ЗначениеЯчейки); 227 | // ЧИСЛО. 228 | ИначеЕсли ТипЗначения = Неопределено 229 | ИЛИ ( ЭтоЧислоXLSX(ЗначениеЯчейки, ФорматСтиля) 230 | И НЕ ЭтоБулевоXLSX(ЗначениеЯчейки, ФорматСтиля) 231 | И НЕ ЭтоВремяXLSX(ЗначениеЯчейки, ФорматСтиля) 232 | И НЕ ЭтоДатаXLSX(ЗначениеЯчейки, ФорматСтиля) ) 233 | Тогда 234 | // Без преобразования. 235 | Иначе 236 | // Прочие форматы. 237 | КонецЕсли; 238 | 239 | Иначе 240 | 241 | Сообщить(""Не удалось преобразовать значение к """"числовому""""(процент, время, дата, число) типу.""); 242 | 243 | КонецЕсли; 244 | 245 | ИначеЕсли ВРег(ТипЗначения) = ""S"" Тогда 246 | 247 | // МассивSharedStrings может быть пустым. 248 | Попытка 249 | ЗначениеЯчейки = СокрЛП(МассивSharedStrings[Число(SheetX.Значение)]); 250 | Исключение 251 | ЗначениеЯчейки = """"; 252 | КонецПопытки; 253 | 254 | ИначеЕсли ВРег(ТипЗначения) = ""STR"" Тогда 255 | 256 | Если ТипЗнч(ЗначениеЯчейки) = Тип(""Строка"") Тогда 257 | ЗначениеЯчейки = СокрЛП(ЗначениеЯчейки); 258 | КонецЕсли; 259 | 260 | КонецЕсли; 261 | КонецЕсли; 262 | 263 | ИмяКолонки = ""N""+ИндексКолонки; 264 | НоваяСтрока[ИмяКолонки] = ЗначениеЯчейки; 265 | // Используется при формировании таблицы на форме обработки. 266 | ШиринаКолонки = ТаблицаРезультат.Колонки[ИмяКолонки].Ширина; 267 | ДлинаСтроки = СтрДлина(СокрЛП(ЗначениеЯчейки)); 268 | ТаблицаРезультат.Колонки[ИмяКолонки].Ширина = ?(ШиринаКолонки < ДлинаСтроки, ДлинаСтроки, ШиринаКолонки); 269 | 270 | КонецЕсли; 271 | КонецЕсли; 272 | КонецЕсли; 273 | КонецЦикла; 274 | Если ((НЕ КонСтрока = 0 И (НомерСтроки + 1) > КонСтрока) 275 | ИЛИ (НЕ КолвоСтрокExcel = 0 И (НомерСтроки + 1) > КолвоСтрокExcel)) Тогда 276 | Прервать; // Окончание диапазона считываемых данных. 277 | КонецЕсли; 278 | КонецЕсли; 279 | КонецЦикла; 280 | 281 | // Завершение работы. 282 | // Закрытие Объектов. 283 | SheetX.Закрыть(); 284 | 285 | УдалитьКолонкиСНулевойШириной(ТаблицаРезультат); 286 | 287 | Возврат ТаблицаРезультат; 288 | 289 | КонецФункции 290 | 291 | &НаСервере 292 | Функция ПредварительнаяОбработкаФайлаXLSX(ФайлEXCEL, ZIPКаталог) 293 | Перем Файл; 294 | 295 | Файл = ПолучитьОбъектФайл(ФайлEXCEL); 296 | Если Файл = Неопределено Тогда 297 | Сообщить(""Невозможно загрузить данные, т.к. невозможно открыть для чтения файл: 298 | |"" + ФайлEXCEL); 299 | Возврат Ложь; 300 | КонецЕсли; 301 | 302 | Если НЕ ВРег(Файл.Расширение) = "".XLSX"" Тогда 303 | Сообщить(""Файл с расширением "" + Файл.Расширение +"" не поддерживается методом NativeXLSX: 304 | |"" + ФайлEXCEL); 305 | Возврат Ложь; 306 | КонецЕсли; 307 | 308 | Если НЕ РаспаковатьXLSXвКаталогВременныхФайлов(ФайлEXCEL, ZIPКаталог) Тогда 309 | Сообщить(""Ошибка распаковки файла. 310 | |Возможно каталог временных файлов занят. 311 | |"" + ФайлEXCEL); 312 | Возврат Ложь; 313 | КонецЕсли; 314 | 315 | Возврат Истина; 316 | 317 | КонецФункции 318 | 319 | &НаСервере 320 | Функция ПолучитьОбъектФайл(Знач ФайлEXCEL) 321 | Перем Файл; 322 | 323 | Если НЕ ЗначениеЗаполнено(ФайлEXCEL) Тогда 324 | Возврат Неопределено; 325 | КонецЕсли; 326 | 327 | Файл = Новый Файл(ФайлEXCEL); 328 | Если НЕ ФайлСуществуетИДоступен(Файл.ПолноеИмя) Тогда 329 | Сообщить(""Файл не существует/не доступен: 330 | |"" + ФайлEXCEL); 331 | Возврат Неопределено; 332 | КонецЕсли; 333 | 334 | Возврат Файл; 335 | 336 | КонецФункции 337 | 338 | &НаСервере 339 | Функция ФайлСуществуетИДоступен(ПолноеИмяФайла) 340 | Перем Файл; 341 | 342 | Файл = Новый Файл(ПолноеИмяФайла); 343 | Если НЕ Файл.Существует() Тогда 344 | Возврат Ложь; 345 | КонецЕсли; 346 | 347 | // Проверка: Занят ли файл другим процессом? 348 | Если НЕ ВРег(Файл.Расширение) = "".DBF"" Тогда 349 | Попытка 350 | ПереместитьФайл(Файл.ПолноеИмя,Файл.ПолноеИмя); 351 | Исключение 352 | Сообщить(""Файл не доступен: 353 | |"" + Файл.ПолноеИмя); 354 | Возврат Ложь; 355 | КонецПопытки; 356 | КонецЕсли; 357 | 358 | Возврат Истина; 359 | 360 | КонецФункции 361 | 362 | &НаСервере 363 | Функция РаспаковатьXLSXвКаталогВременныхФайлов(ФайлEXCEL, ZIPКаталог) 364 | Перем ZIPФайл; 365 | 366 | Попытка 367 | УдалитьФайлы(ZIPКаталог); 368 | 369 | ZIPФайл = Новый ЧтениеZipФайла; 370 | ZIPФайл.Открыть(ФайлEXCEL); 371 | ZIPФайл.ИзвлечьВсе(ZIPКаталог, РежимВосстановленияПутейФайловZIP.Восстанавливать); 372 | Возврат Истина; 373 | Исключение 374 | Возврат Ложь; 375 | КонецПопытки; 376 | 377 | Возврат Истина; 378 | 379 | КонецФункции 380 | 381 | &НаСервере 382 | Функция ИзвлечьДанныеИзФайла_StylesXML(ZIPКаталог, СоответствиеNumFmtIdFormatCode) 383 | Перем Файл, Styles; 384 | Перем МассивNumFmtId, ит; 385 | 386 | МассивNumFmtId = Новый Массив; 387 | СоответствиеNumFmtIdFormatCode = Новый Соответствие; 388 | 389 | Файл = Новый Файл(ZIPКаталог + ""XL\Styles.xml""); 390 | Если НЕ Файл.Существует() Тогда 391 | Возврат МассивNumFmtId; 392 | КонецЕсли; 393 | 394 | Styles = Новый ЧтениеXML; 395 | Styles.ОткрытьФайл(Файл.ПолноеИмя); 396 | 397 | Пока Styles.Прочитать() Цикл 398 | Если ВРег(Styles.Имя) = ВРег(""numFmt"") И Styles.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда 399 | СоответствиеNumFmtIdFormatCode.Вставить(Styles.ЗначениеАтрибута(""numFmtId""), ВРег(Styles.ЗначениеАтрибута(""formatCode""))); 400 | КонецЕсли; 401 | Если ВРег(Styles.Имя) = ВРег(""cellXfs"") Тогда 402 | Пока Styles.Прочитать() Цикл 403 | Если ВРег(Styles.Имя) = ВРег(""xf"") И Styles.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда 404 | МассивNumFmtId.Добавить(Styles.ЗначениеАтрибута(""numFmtId"")); 405 | КонецЕсли; 406 | КонецЦикла; 407 | КонецЕсли; 408 | КонецЦикла; 409 | 410 | // Завершение работы. 411 | // Закрытие Объектов. 412 | Styles.Закрыть(); 413 | 414 | // Проверка сопоставления кодов массива и соответствия. 415 | // MS Office может не формировать в xml-файле описание стиля форматирования для ячейки. 416 | // LibreOffice формирует в xml-файле необходимые описания стиля форматирования ячейки. 417 | Для Каждого ит ИЗ МассивNumFmtId Цикл 418 | Если СоответствиеNumFmtIdFormatCode.Получить(ит) = Неопределено Тогда 419 | Если ит = ""0"" Тогда // Стандарт для числа (Целое число). 420 | СоответствиеNumFmtIdFormatCode.Вставить(ит, ""GENERAL""); 421 | ИначеЕсли ит = ""9"" ИЛИ ит = ""10"" Тогда // Форматы для % (""0%"", ""0.00%""). 422 | СоответствиеNumFmtIdFormatCode.Вставить(ит, ""0%""); 423 | ИначеЕсли ит = ""14"" ИЛИ ит = ""16"" Тогда // Форматы для даты. 424 | СоответствиеNumFmtIdFormatCode.Вставить(ит, ""DD.MM.YYYY""); 425 | ИначеЕсли ит = ""45"" ИЛИ ит = ""46"" ИЛИ ит = ""47"" Тогда // Форматы для времени. 426 | СоответствиеNumFmtIdFormatCode.Вставить(ит, ""HH:MM:SS""); 427 | КонецЕсли; 428 | КонецЕсли; 429 | КонецЦикла; 430 | 431 | Возврат МассивNumFmtId; 432 | 433 | КонецФункции 434 | 435 | &НаСервере 436 | Функция ИзвлечьДанныеИзФайла_SharedStringsXML(ZIPКаталог) 437 | Перем Файл, SharedStrings; 438 | Перем МассивSharedStrings; 439 | 440 | // Если в файле EXCEL не содержится значений, имеющих тип ""СТРОКА"", то файл ""SharedStrings.xml"" не формируется. 441 | 442 | МассивSharedStrings = Новый Массив; 443 | 444 | Файл = Новый Файл(ZIPКаталог + ""XL\SharedStrings.xml""); 445 | Если НЕ Файл.Существует() Тогда 446 | Возврат МассивSharedStrings; 447 | КонецЕсли; 448 | 449 | SharedStrings = Новый ЧтениеXML; 450 | SharedStrings.ОткрытьФайл(Файл.ПолноеИмя); 451 | 452 | ФлагСтрокаЗаписана = Ложь; 453 | 454 | Пока SharedStrings.Прочитать() Цикл 455 | Если ВРег(SharedStrings.Имя) = ""SI"" и SharedStrings.ТипУзла = ТипУзлаXML.НачалоЭлемента тогда 456 | ФлагСтрокаЗаписана = Ложь; 457 | КонецЕсли; 458 | 459 | Если ВРег(SharedStrings.Имя) = ""#TEXT"" Тогда 460 | МассивSharedStrings.Добавить(SharedStrings.Значение); 461 | ФлагСтрокаЗаписана = Истина; 462 | КонецЕсли; 463 | 464 | Если ВРег(SharedStrings.Имя) = ""SI"" и SharedStrings.ТипУзла = ТипУзлаXML.КонецЭлемента и не ФлагСтрокаЗаписана тогда 465 | //встретили пустую строку! 466 | МассивSharedStrings.Добавить(""""); 467 | КонецЕсли; 468 | 469 | КонецЦикла; 470 | 471 | // Завершение работы. 472 | // Закрытие Объектов. 473 | SharedStrings.Закрыть(); 474 | 475 | Возврат МассивSharedStrings; 476 | 477 | КонецФункции 478 | 479 | &НаСервере 480 | Функция ПолучитьМассивИменКолонокНаЛистеXLSX(SheetX) 481 | Перем ДиапазонДанных, ДиапазонКолонок, ПерваяКолонка, ПоследняяКолонка, НомерПервойК, НомерПоследнейК; 482 | Перем Подсчет, ИмяКолонки; 483 | Перем МассивИменКолонокXLSX, КолвоКолонокEXCEL; 484 | 485 | МассивИменКолонокXLSX = Новый Массив; 486 | 487 | Подсчет = Ложь; 488 | // Считать очередной узел XML. 489 | Пока SheetX.Прочитать() Цикл 490 | // DIMENSION. 491 | Если ВРег(SheetX.Имя) = ""DIMENSION"" И SheetX.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда 492 | ДиапазонДанных = SheetX.ПолучитьАтрибут(""ref""); 493 | ДиапазонКолонок = ЗаменитьОдниСимволыДругими(""0123456789"", ДиапазонДанных, """"); 494 | ПерваяКолонка = Лев(ДиапазонКолонок, Найти(ДиапазонКолонок ,"":"") - 1); 495 | ПоследняяКолонка= Сред(ДиапазонКолонок, Найти(ДиапазонКолонок ,"":"") + 1); 496 | НомерПервойК = НомерКолонкиДесятичный(ПерваяКолонка); 497 | НомерПоследнейК = НомерКолонкиДесятичный(ПоследняяКолонка); 498 | КонецЕсли; 499 | // Подсчет по 1-ой строке. 500 | Если ВРег(SheetX.Имя) = ""ROW"" Тогда 501 | Если SheetX.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда 502 | // Начало отсчета. 503 | Подсчет = Истина; 504 | ИначеЕсли SheetX.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда 505 | // Окончание отсчета. 506 | Прервать; 507 | КонецЕсли; 508 | КонецЕсли; 509 | Если Подсчет И ВРег(SheetX.Имя) = ""C"" И SheetX.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда 510 | ИмяКолонки = SheetX.ПолучитьАтрибут(""r""); 511 | ИмяКолонки = ЗаменитьОдниСимволыДругими(""0123456789"", ИмяКолонки, """"); 512 | МассивИменКолонокXLSX.Добавить(ИмяКолонки); 513 | КонецЕсли; 514 | КонецЦикла; 515 | 516 | КолвоКолонокEXCEL = МассивИменКолонокXLSX.Количество(); 517 | Если НЕ НомерПоследнейК = Неопределено Тогда 518 | Если КолвоКолонокEXCEL < НомерПоследнейК Тогда 519 | //СУУ_ЕНС 27 11 17. в контексте текущей задачи лишние сообщения ни к чему, если и так все работает нормально 520 | //Сообщить(""Строка заголовков колонок (1-я строка) заполнена не полностью: 521 | //|К-во колонок строки меньше объявленной: "" + КолвоКолонокEXCEL + ""<"" + НомерПоследнейК); 522 | ДополнитьМассивИменКолонокXLSX(НомерПоследнейК, МассивИменКолонокXLSX); 523 | ИначеЕсли КолвоКолонокEXCEL > НомерПоследнейК Тогда 524 | //СУУ_ЕНС 27 11 17. в контексте текущей задачи лишние сообщения ни к чему, если и так все работает нормально 525 | //Сообщить(""Строка заголовков колонок (1-я строка) содержит больше колонок, чем объявлено: 526 | //|К-во колонок строки больше объявленной:"" + КолвоКолонокEXCEL + "">"" + НомерПоследнейК); 527 | КонецЕсли; 528 | КонецЕсли; 529 | 530 | Возврат МассивИменКолонокXLSX; 531 | 532 | КонецФункции 533 | 534 | &НаСервере 535 | Функция НомерКолонкиДесятичный(ИмяКолонкиXLSX) 536 | Перем Латиница, ДлинаНомера, Поз, ит; 537 | Перем НомерКолонки; 538 | 539 | Латиница = ""ABCDEFGHIJKLMNOPQRSTUVWXYZ""; // 26. 540 | ДлинаНомера = СтрДлина(ИмяКолонкиXLSX); 541 | НомерКолонки = 0; 542 | Для ит = 1 ПО ДлинаНомера Цикл 543 | Поз = Найти(Латиница, Сред(ИмяКолонкиXLSX, (ДлинаНомера + 1 - ит), 1)); 544 | НомерКолонки = НомерКолонки + Поз * Pow(26, ит - 1); 545 | КонецЦикла; 546 | 547 | Возврат НомерКолонки; 548 | 549 | КонецФункции 550 | 551 | &НаСервере 552 | Процедура ДополнитьМассивИменКолонокXLSX(Знач КолвоКолонокExcel, МассивИменКолонокXLSX, Индекс = - 1) 553 | Перем Алфавит, ит, Буква; 554 | 555 | Алфавит = РазложитьСтрокуВМассивПодстрок(""A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z"", "",""); 556 | 557 | Если МассивИменКолонокXLSX.Количество() >= КолвоКолонокExcel Тогда 558 | Возврат; 559 | КонецЕсли; 560 | 561 | Если Индекс > Алфавит.Количество() - 1 Тогда 562 | Возврат; 563 | КонецЕсли; 564 | 565 | Буква = ?(Индекс = -1, """", Алфавит[Индекс]); 566 | Для ит = 0 ПО Алфавит.Количество() - 1 Цикл 567 | Если МассивИменКолонокXLSX.Найти(Буква + Алфавит[ит]) = Неопределено Тогда 568 | МассивИменКолонокXLSX.Добавить(Буква + Алфавит[ит]); 569 | КонецЕсли; 570 | Если МассивИменКолонокXLSX.Количество() >= КолвоКолонокExcel Тогда 571 | Возврат; 572 | КонецЕсли; 573 | КонецЦикла; 574 | 575 | Если МассивИменКолонокXLSX.Количество() > КолвоКолонокExcel Тогда 576 | Возврат; 577 | Иначе 578 | Индекс = Индекс + 1; 579 | ДополнитьМассивИменКолонокXLSX(КолвоКолонокExcel, МассивИменКолонокXLSX, Индекс); 580 | КонецЕсли; 581 | 582 | Возврат; 583 | 584 | КонецПроцедуры 585 | 586 | // Функция ""расщепляет"" строку на подстроки, используя заданный 587 | // разделитель. Разделитель может иметь любую длину. 588 | // Если в качестве разделителя задан пробел, рядом стоящие пробелы 589 | // считаются одним разделителем, а ведущие и хвостовые пробелы параметра Стр 590 | // игнорируются. 591 | // Например, 592 | // РазложитьСтрокуВМассивПодстрок("",один,,,два"", "","") возвратит массив значений из пяти элементов, 593 | // три из которых - пустые строки, а 594 | // РазложитьСтрокуВМассивПодстрок("" один два"", "" "") возвратит массив значений из двух элементов 595 | // 596 | // Параметры: 597 | // Стр - строка, которую необходимо разложить на подстроки. 598 | // Параметр передается по значению. 599 | // Разделитель - строка-разделитель, по умолчанию - запятая. 600 | // 601 | // Возвращаемое значение: 602 | // массив значений, элементы которого - подстроки 603 | // 604 | &НаСервере 605 | Функция РазложитьСтрокуВМассивПодстрок(Знач Стр, Разделитель = "","") 606 | 607 | МассивСтрок = Новый Массив(); 608 | Если Разделитель = "" "" Тогда 609 | Стр = СокрЛП(Стр); 610 | Пока 1 = 1 Цикл 611 | Поз = Найти(Стр, Разделитель); 612 | Если Поз = 0 Тогда 613 | МассивСтрок.Добавить(СокрЛП(Стр)); 614 | Возврат МассивСтрок; 615 | КонецЕсли; 616 | МассивСтрок.Добавить(СокрЛП(Лев(Стр, Поз - 1))); 617 | Стр = СокрЛ(Сред(Стр, Поз)); 618 | КонецЦикла; 619 | Иначе 620 | ДлинаРазделителя = СтрДлина(Разделитель); 621 | Пока 1 = 1 Цикл 622 | Поз = Найти(Стр, Разделитель); 623 | Если Поз = 0 Тогда 624 | Если (СокрЛП(Стр) <> """") Тогда 625 | МассивСтрок.Добавить(СокрЛП(Стр)); 626 | КонецЕсли; 627 | Возврат МассивСтрок; 628 | КонецЕсли; 629 | МассивСтрок.Добавить(СокрЛП(Лев(Стр,Поз - 1))); 630 | Стр = Сред(Стр, Поз + ДлинаРазделителя); 631 | КонецЦикла; 632 | КонецЕсли; 633 | 634 | КонецФункции 635 | 636 | &НаСервере 637 | Функция ЭтоЧислоXLSX(Знач ЗначениеЯчейки, Знач ФорматСтиля) 638 | 639 | Если ( ВРег(ФорматСтиля) = ""GENERAL"" 640 | ИЛИ ВРег(ФорматСтиля) = ""STANDARD"" 641 | ИЛИ Найти(ФорматСтиля, ""0"") > 0 ) 642 | Тогда 643 | Возврат Истина; 644 | КонецЕсли; 645 | 646 | Возврат Ложь; 647 | 648 | КонецФункции 649 | 650 | &НаСервере 651 | Функция ЭтоПроцентXLSX(Знач ЗначениеЯчейки, Знач ФорматСтиля) 652 | 653 | Если ( Найти(ФорматСтиля, ""%"") > 0 ) 654 | Тогда 655 | Возврат Истина; 656 | КонецЕсли; 657 | 658 | Возврат Ложь; 659 | 660 | КонецФункции 661 | 662 | &НаСервере 663 | Функция ЭтоБулевоXLSX(ЗначениеЯчейки, ФорматСтиля) 664 | 665 | Если (ЗначениеЯчейки = 0 ИЛИ ЗначениеЯчейки = 1) 666 | И Найти(ВРег(ФорматСтиля), ""ИСТИНА"") > 0 ИЛИ Найти(ВРег(ФорматСтиля), ""ЛОЖЬ"") > 0 667 | ИЛИ Найти(ВРег(ФорматСтиля), ""TRUE"") > 0 ИЛИ Найти(ВРег(ФорматСтиля), ""FALSE"") > 0 668 | Тогда 669 | Возврат Истина; 670 | КонецЕсли; 671 | 672 | Возврат Ложь; 673 | 674 | КонецФункции 675 | 676 | &НаСервере 677 | Функция ЭтоДатаXLSX(Знач ЗначениеЯчейки, Знач ФорматСтиля) 678 | 679 | Если ЗначениеЯчейки = Цел(ЗначениеЯчейки) И 680 | ( Найти(ФорматСтиля, ""DD"") > 0 681 | ИЛИ Найти(ФорматСтиля, ""MM"") > 0 682 | ИЛИ Найти(ФорматСтиля, ""YY"") > 0 683 | ИЛИ Найти(ФорматСтиля, ""QQ"") > 0 684 | ИЛИ Найти(ФорматСтиля, ""WW"") > 0 ) 685 | Тогда 686 | Возврат Истина; 687 | КонецЕсли; 688 | 689 | Возврат Ложь; 690 | 691 | КонецФункции 692 | 693 | &НаСервере 694 | Функция ЭтоВремяXLSX(Знач ЗначениеЯчейки, Знач ФорматСтиля) 695 | 696 | Если ЗначениеЯчейки < 1 И 697 | ( Найти(ФорматСтиля, ""HH:"") > 0 698 | ИЛИ Найти(ФорматСтиля, ""[HH]:"") > 0 699 | ИЛИ Найти(ФорматСтиля, ""[H]:"") > 0 700 | ИЛИ Найти(ФорматСтиля, ""MM:"") > 0 701 | ИЛИ Найти(ФорматСтиля, "":SS"") > 0 ) 702 | Тогда 703 | Возврат Истина; 704 | КонецЕсли; 705 | 706 | Возврат Ложь; 707 | 708 | КонецФункции 709 | 710 | &НаСервере 711 | Функция КонвертироватьЧислоXLSXвДату(Знач Число) 712 | Перем Дата1900, Разница, ДатаРезультат; 713 | 714 | Дата1900 = Дата(""19000101""); 715 | 716 | Разница = Число - 2; // EXCEL ошибочно считает 1900-й год високосным. 717 | Разница = ?(Разница < 0, 0, Разница); 718 | 719 | ДатаРезультат = Дата1900 + Разница * 24 * 60 * 60; 720 | 721 | Возврат ДатаРезультат; 722 | 723 | КонецФункции 724 | 725 | &НаСервере 726 | Функция КонвертироватьЧислоXLSXвДатуВремя(Знач Число) 727 | Перем КВоСекунд; 728 | Перем ВремяРезультат; 729 | 730 | // 0,0000115740740740741 = 1 сек. 731 | // 1 = 24 часа 00 мин 00 сек. 732 | 733 | Если ТипЗнч(Число) = Тип(""Число"") Тогда 734 | КВоСекунд = Число * 100000 / 1.15740740740741; 735 | КВоСекунд = Окр(КВоСекунд); 736 | Иначе 737 | Сообщить(""Ошибка определения значения типа """"Время"""".""); 738 | КонецЕсли; 739 | 740 | ВремяРезультат = Дата(""19000101000000"") + КВоСекунд; 741 | 742 | Возврат ВремяРезультат; 743 | 744 | КонецФункции 745 | 746 | &НаСервере 747 | Функция ПолучитьЧислоВСтепениИзСтроковогоЗначения(Знач ЗначениеЯчейки) 748 | Перем Поз1Е, Степень; 749 | Перем Значение; 750 | 751 | Если Найти(ЗначениеЯчейки, ""E-"") > 0 Тогда 752 | Поз1Е = Найти(ЗначениеЯчейки, ""E-""); 753 | Степень = Сред(ЗначениеЯчейки, Поз1Е+2); 754 | Значение = Лев(ЗначениеЯчейки, Поз1Е-1); 755 | Попытка 756 | Степень = Число(Степень); 757 | Значение = Число(Значение) / Pow(10, Степень); 758 | Исключение 759 | Значение = ЗначениеЯчейки; 760 | КонецПопытки; 761 | ИначеЕсли Найти(ЗначениеЯчейки, ""E+"") > 0 Тогда 762 | Поз1Е = Найти(ЗначениеЯчейки, ""E+""); 763 | Степень = Сред(ЗначениеЯчейки, Поз1Е+2); 764 | Значение = Лев(ЗначениеЯчейки, Поз1Е-1); 765 | Попытка 766 | Степень = Число(Степень); 767 | Значение = Число(Значение) * Pow(10, Степень); 768 | Исключение 769 | Значение = ЗначениеЯчейки; 770 | КонецПопытки; 771 | Иначе 772 | Значение = ЗначениеЯчейки; 773 | КонецЕсли; 774 | 775 | Возврат Значение; 776 | 777 | КонецФункции 778 | 779 | &НаСервере 780 | Функция ЗаменитьОдниСимволыДругими(ЗаменяемыеСимволы, Строка, СимволыЗамены) 781 | Результат = Строка; 782 | Для НомерСимвола = 1 По СтрДлина(ЗаменяемыеСимволы) Цикл 783 | Результат = СтрЗаменить(Результат, Сред(ЗаменяемыеСимволы, НомерСимвола, 1), Сред(СимволыЗамены, НомерСимвола, 1)); 784 | КонецЦикла; 785 | Возврат Результат; 786 | КонецФункции 787 | 788 | &НаСервере 789 | Процедура УдалитьКолонкиСНулевойШириной(ТаблицаРезультат) 790 | Перем МассивПустыхКолонок; 791 | // Найдем пустые колонки. 792 | МассивПустыхКолонок = Новый Массив; 793 | Для Каждого Колонка ИЗ ТаблицаРезультат.Колонки Цикл 794 | Если Колонка.Ширина = 0 Тогда 795 | МассивПустыхКолонок.Добавить(Колонка.Имя); 796 | КонецЕсли; 797 | КонецЦикла; 798 | // Удалим пустые колонки. 799 | Для Каждого ПустаяКолонка ИЗ МассивПустыхКолонок Цикл 800 | ТаблицаРезультат.Колонки.Удалить(ПустаяКолонка); 801 | КонецЦикла; 802 | КонецПроцедуры 803 | ", 804 | {4,1, 805 | {9, 806 | {1},0,"Объект", 807 | {1,0}, 808 | {"Pattern", 809 | {"#",312233da-5e39-45fa-b3d8-e88d1041a136} 810 | }, 811 | {0, 812 | {0, 813 | {"B",1},0} 814 | }, 815 | {0, 816 | {0, 817 | {"B",1},0} 818 | }, 819 | {0,0}, 820 | {0,0},1,0,0,0, 821 | {0,0}, 822 | {0,0} 823 | },0,0, 824 | {#base64:77u/PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxTZXR0 825 | aW5ncyB4bWxucz0iaHR0cDovL3Y4LjFjLnJ1LzguMS9kYXRhLWNvbXBvc2l0aW9u 826 | LXN5c3RlbS9zZXR0aW5ncyIgeG1sbnM6ZGNzY29yPSJodHRwOi8vdjguMWMucnUv 827 | OC4xL2RhdGEtY29tcG9zaXRpb24tc3lzdGVtL2NvcmUiIHhtbG5zOnN0eWxlPSJo 828 | dHRwOi8vdjguMWMucnUvOC4xL2RhdGEvdWkvc3R5bGUiIHhtbG5zOnN5cz0iaHR0 829 | cDovL3Y4LjFjLnJ1LzguMS9kYXRhL3VpL2ZvbnRzL3N5c3RlbSIgeG1sbnM6djg9 830 | Imh0dHA6Ly92OC4xYy5ydS84LjEvZGF0YS9jb3JlIiB4bWxuczp2OHVpPSJodHRw 831 | Oi8vdjguMWMucnUvOC4xL2RhdGEvdWkiIHhtbG5zOndlYj0iaHR0cDovL3Y4LjFj 832 | LnJ1LzguMS9kYXRhL3VpL2NvbG9ycy93ZWIiIHhtbG5zOndpbj0iaHR0cDovL3Y4 833 | LjFjLnJ1LzguMS9kYXRhL3VpL2NvbG9ycy93aW5kb3dzIiB4bWxuczp4cz0iaHR0 834 | cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiIHhtbG5zOnhzaT0iaHR0cDov 835 | L3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiLz4=} 836 | }, 837 | {0,0}, 838 | {0,1, 839 | {6, 840 | {1,409b9a53-7f7e-4178-86c1-33176c7c7a7a},"ПрочитатьXLSX", 841 | {1,1, 842 | {"ru","Прочитать XLSX"} 843 | }, 844 | {1,1, 845 | {"ru","Прочитать XLSX"} 846 | }, 847 | {0, 848 | {0, 849 | {"B",1},0} 850 | }, 851 | {0,0,0}, 852 | {3,0, 853 | {0},"",-1,-1,1,0},"ПрочитатьXLSX",3,0,0, 854 | {0,0} 855 | } 856 | }, 857 | {0,0}, 858 | {0,0} 859 | } --------------------------------------------------------------------------------