Поради тим, хто програмує на vb & vba, КомпьютерПресс

Для візуалізації інформації можна уявити послідовність двійкових байтів у вигляді рядка шістнадцятирічних символів (кожен байт представлений парою таких символів). Рішення у цій задачі досить просте, але слід пам'ятати, що в VB рядок може містити як довільну послідовність байтів (інакше кажучи, символів в однобайтном ANSI-кодуванні), так і набір Unicode-символів (цей варіант використовується в 32-розрядних версіях VB) . В останньому випадку кожен символ буде займати пару послідовних байтів.

Функція перетворення в шістнадцятковий вид може бути реалізована в такому вигляді:

Як бачите, функція дозволяє працювати і з довільними байтами, і з Unicode-символами. В останньому випадку (blnBytes = False) проводиться автоматичне перетворення з Unicode в ANSI. Слід звернути увагу на те, що таке перетворення змінної не відбивається на вмісті початкового рядка в зухвалій програмі, оскільки використовується метод передачі параметра «за значенням» (ByVal).

Робота функції ConvertBytesToHexString демонструється на наступному тестовому прикладі:

Порівняйте отримані результати, щоб краще зрозуміти відмінність Unicode- і ANSI-кодувань. У першому випадку кожен символ представлений двома байтами (байт - двома шестнадцатерічнимі символами): перший байт - власне код символу, а другий - номер кодової таблиці (для англійської він дорівнює 00, для російської - 04). Для англійських символів коди Unicode (точніше, його перший байт) і ASNI однакові.

Word містить кілька спеціальних імен для макросів, автоматично виконуються при деяких зумовлених події. Їх застосування дозволяє створити альтернативні варіанти обробки замість вбудованих функцій. Наведемо список цих імен з моментами їх виконання:

AutoExec - при запуску Word або завантаженні глобального шаблону

AutoNew - при створенні нового документа

AutoOpen - при відкритті існуючого документа

AutoClose - при закритті документа

AutoExit - при закритті Word або вивантаженні глобального шаблону

Виконавши вказаний код, ми, однак, виявимо, що, виявляється, в цьому випадку новий рядок меню не тільки створюється, але і замінює вже існуючу. Точніше, ситуація виглядає наступним чином: в додатку може бути кілька рядків меню, але видимим залишається тільки одне. При цьому у вікні Customize видно всі наявні рядки меню, але керувати станом «мабуть / приховано» (у віконці прапорця) тут не можна, а доступна лише операція видалення користувальницької рядка меню.

Для управління виводу на екран потрібної рядка меню можна написати спеціальну макрокоманду, яка використовує діалогове вікно зі списком (для виклику макрокоманди краще створити кнопку на панелі інструментів або закріпити на ній комбінацію клавіш):

Слід звернути увагу на наступні моменти в наведеному тут коді:

  1. Установка для деякого рядка стану видимості автоматично приховує інші рядки.
  2. На жаль, у об'єкта CommandBar немає властивості, яке дозволило б визначити тип об'єкта (меню, панель та ін.). Тому ми змушені робити пошук по контексту імені об'єкта (отже, потрібно, щоб ім'я містило «Menu Bar»).
  3. У функції InStr використовується текстовий режим пошуку (при будь-якому регістрі букв). Але в цьому випадку чомусь обов'язково слід вказувати перший (необов'язковий) параметр виклику.

Звернувшись до макрокоманді MenuBarVisible, ми отримаємо діалогове вікно зі списком рядків меню (рис. 1). Вибираючи елементи списку, ми будемо відразу бачити на екрані потрібний рядок меню.

Подальше формування меню може виглядати приблизно так:

В результаті у нас вийде меню з однією командою і посиланням на них (рис. 2). У зв'язку з цим слід мати на увазі, що опису елементів управління CommandBarPopup і CommandBarButton жорстко фіксують його тип, а CommandBarControl дозволяє здійснювати динамічне визначення типу.

Властивості документа - це такі параметри, які ви можете побачити, відкривши вікно Properties (Властивості). Там знаходяться два набору властивостей - вбудовані і призначені для користувача. Прочитати їх програмним чином можна за допомогою відповідно об'єктів BuildInDocumentProperties і CustomDocumentProperties, наприклад таким чином:

Тут потрібно звернути увагу на необхідність використання програмної обробки помилок. Справа в тому, що якщо якісь параметри не визначені (наприклад, дата останньої друку для новоствореного документа), то звернення до властивості Value викликає помилку.

Можна здійснити читання конкретного властивості документа, зокрема кількості сторінок, вказавши його індекс або ім'я (наведені нижче рядки ідентичні):

Однак більш правильним є використання вбудованих констант VBA:

Це обумовлено тим, що в наступній версії Word, цілком можливо, зміниться нумерація і навіть назви властивостей. Ще раз підкреслимо, що правильне читання властивостей має виглядати наступним чином:

Один з наших читачів виявив, що з якоїсь причини цей елемент керування не «хоче» працювати в середовищі VBA. Дійсно, при спробі перемістити його з панелі інструментів на форму видається повідомлення про помилку: «Unexpected call to method or property access».

Чому таке відбувається, ми зрозуміти не змогли, але знайшли альтернативне вирішення питання: чи можна взагалі обійтися без застосування елемента управління, працюючи безпосередньо з об'єктом. Для цього потрібно за допомогою команди Tools | Reference підключити бібліотеку Microsoft Srcipt Control 1.0 і використовувати такий код, звертаючись безпосередньо до об'єкта:

Рада 385. На що потрібно звернути увагу при вимірі інтервалів часу

В одній з телеконференцій ми знайшли питання про «аномальному поведінці функції Timer. У документації сказано, що функція повертає значення поточного часу доби в секундах (у вигляді величини типу Single), з чого з усією очевидністю випливає, що вона повинна монотонно зростати (але опівночі відлік знову почнеться з нуля!). Однак задав це питання виявив, що іноді значення змінної sngDiff в наведеному нижче фрагменті коду, може виявитися негативним.

Цікаво, що якщо написати обчислення проміжку часу як:

то все починає працювати як слід.

У чому ж тут заковика? Ситуація дійсно здається дивною, але тільки на перший погляд. Справа в тому, що функція Timer працює на рівні точності секунд і не годиться для обробки тисячних часток секунди. При виведенні значення Timer ви побачите число лише з двома знаками після коми.

Очевидно, що при перетворенні часу з якогось внутрішнього формату відбувається деяка втрата точності. Отже, треба знати організацію самої функції Timer, але цілком імовірно, що вона має власний формат даних. Тому можливо, що при виконанні:

остання змінна перетворюється з Single у внутрішній формат Timer, і в цей момент відбувається втрата точності в останньому розряді. Загалом, це досить звичайне явище, коли ви займаєтеся перетворенням форматів числових даних на межі точності. Спробуйте виконати такий приклад:

Здавалося б, отримання повідомлення «Ну, справи!» В принципі неможливо. Однак воно буде з'являтися кожного разу, якщо ви зробите таке визначення типів даних:

Це означає, що в даному випадку буде відбуватися зміна значення числа при перетворенні його з речового формату в цілочисельний (це ми до того, що точний внутрішній формат Timer нам не відомий).

Отже, для зазначених проміжків часу Timer просто не підходить. Що ж робити?

У раді 193 для більш точного вимірювання проміжків часу ми рекомендували використовувати функцію GetTickCount:

Вона видає час в мілісекундах з моменту останнього старту або перезавантаження операційної системи (тобто обнулення лічильника буде відбуватися тільки через 49 діб безперервної роботи комп'ютера). Зверніть увагу, що навіть для наносекундних інтервалів час не піде у зворотний бік, так як ми маємо справу з уже перетвореними цілочисельними значеннями.

Ми вже кілька разів повторювали цю раду і зараз просто хочемо навести ще одне підтвердження його правильності.

Часом в програмах доводиться зустрічати такі логічні конструкції:

В даному випадку цей код працює правильно, але потенційно загрожує надійної (прогнозованої) роботі програми. Загроза полягає в тому, що після ключового слова If має йти логічне умова. Тому строгий синтаксис мови повинен допускати наявність коду тільки наступного виду:

Однак, на жаль, VB дозволяється використовувати і такий запис:

Ця запис насправді еквівалентна нижчеподаній синтаксично правильної конструкції:

Працездатність цього коду визначається тим, що будь-який ненульовий ціле число перетворюється в логічне значення True і, отже, подальша перевірка спрацьовує вірно. Отже, в чому ж полягає небезпека для надійності програми?

Припустимо, що тепер ми хочемо модифікувати код таким чином, щоб деякі дії виконувалися при порожньому значенні рядка. Здавалося б, для цього потрібно просто замінити код умови, використовуючи логічне заперечення:

Але тут ви виявите неприємну несподіванку: повідомлення «Порожнє значення» буде видаватися завжди - при будь-якому значенні строкової змінної.

Дійсно, наведені нижче рядки коду еквівалентні:

І ці рядки також еквівалентні:

Таке відбувається тому, що спочатку виконується логічна інверсія цілої змінної, яка лише потім перетворюється в логічного значення.

Щоб не мучитися з подібними проблемами, записуйте логічні вирази тільки в явному вигляді. При цьому і логіка програми виглядає набагато зрозуміліше:

А тепер погляньте на отриманий результат (рис. 3). При всій схожості ми бачимо одне принципове розходження: значення атрибутів записані в форматі міжнародних регіональних установок (незалежно від установок конкретної операційної системи), а елементів - в форматі національних установок даного комп'ютера. Це означає, що нас очікують певні проблеми при передачі інформації між системами з різними регіональними установками.

Ось як виглядає код читання записаного раніше XML-файла:

В обох випадках ми начебто отримуємо однаково правильні результати. Але є один важливий нюанс: перший варіант працює з міжнародним форматом даних і тому не залежить від регіональних установок, а другий буде працювати тільки за умови, що регіональні установки джерела і приймача інформації збігаються.

Зовсім недавно компанія Cougar представила нову серію блоків живлення для традиційних ПК - VTX, орієнтовану на користувачів з обмеженим бюджетом. У цьому огляді буде розглянута модель Cougar VTX600, яка завдяки своїм характеристикам буде однією з найбільш затребуваних в цій лінійці блоків живлення

На щорічному заході Capsaicin SIGGRAPH в Лос-Анджелесі компанія AMD зміцнила свої позиції на ринку ПК класу high-end з новими процесорами Ryzen Threadripper і GPU «Vega»

Для простого і зручного побудови мереж рядовими користувачами компанія ZyXEL випустила чергову версію свого Інтернет-центру для підключення до мереж 3G / 4G через USB-модем з точкою доступу Wi-Fi - ZyXEL Keenetic 4G III, який ми і розглянемо в цьому огляді

До своєї і так великій родині роутерів і маршрутизаторів фірма ASUS недавно додала дві вельми цікаві моделі: флагманську 4G-AC55U і більш просту 4G-N12. У даній статті буде розглянута флагманська модель ASUS 4G-AC55U

Молода, але амбіційна компанія KREZ на початку цього року випустила нову, оригінальну модель ноутбука KREZ Ninja (модель TM1102B32) під керуванням Windows 10. Оскільки цей комп'ютер має поворотний екран, він може служити універсальним рішенням - його можна з успіхом використовувати і для роботи, і для навчання, і для ігор

Якщо ви часто друкуєте фотографії та вже втомилися міняти картриджі в своєму принтері, зверніть увагу на МФУ Epson L850. Великий ресурс витратних матеріалів, чудова якість відбитків, найширший набір функціональних можливостей - ось лише деякі з переваг даної моделі

Схожі статті