Программирование 1С. Урок 5

В этом уроке продолжим изучение 1С. На прошлом занятии мы начали пробовать делать свои первые отчеты на базе СКД, но глубоко не вникали в эту тему. На этом уроке будем более расширенно погружаться в эту тему.

Настало время более подробно познакомиться с языком запросов 1С. В основе этого языка, как я уже говорил, находится язык SQL. Однако, в 1С он используется с одной стороны не полностью, а с другой, ввиду специфики самого 1С, в него добавлены те конструкции, которых нет в базовом SQL. В 1С язык используется для получения данных из базы. Обратиться можно практически ко всему, что хранит в себе рабочая среда конфигурации 1С. Т.е. мы создаём справочники, документы, регистры, и всё это можно получить через язык запросов. Сам же этот язык используется не только для СКД, но и в других областях программирования 1С, например, при проведении документов, при написании различных обработок, выгрузки данных в другие системы и т.п. Для примера возьмем нашу конфигурации. Помните, на одном из прошлых уроков мы делали документ поступления и документы списания. Давайте рассмотрим типичную для любого бизнеса ситуацию, опять-таки на примере чайников. Мы купили 5 чайников одной и той же модели по 1000 руб чтобы подарить их на Новый год нашим гостям. Потом узнали, что гостей будет не 5 человек, а 8. Кого-то обидеть было бы нехорошо, по этому решили докупить ещё 3 таких же чайника. Приходим в магазин, а они уже не по 1000, а по 1500 руб за штуку. Делать нечего, купили ещё три штуки. Потом, оказалось, что гостей пришло не 8, как мы ожидали, а 6 человек. Т.е. у нас останется 2 чайника лишних и мы решили их продать по объявлению. Вопрос на засыпку – какая себестоимость каждого из 2 оставшихся чайников? За какую цену нам их продавать чтобы не остаться “в минусе”? Ведь мы дарили 6 чайников и конечно же не маркировали их за сколько они нам обошлись. А покупали по разным ценам – по 1000 и 1500. Как узнать теперь сколько стоит каждый чайник из этих двух? Тут одним из подходов в такой ситуации является метод средневзвешенной цены по формуле:

СредневзвешеннаяЦена = (Количество1 * Цена1 + Количество2 * Цена + …) / (Количество1 + Количество2 + …)

Т.е. мы суммируем произведение количество на цену при каждой покупке. Получается, что после приобретения всех 8 чайников у нас будет так:

СредневзвешеннаяЦена = (5 * 1000 + 3 * 1500) / (5 + 3) = 1187.50 руб.

Это как раз и есть та самая себестоимость каждого чайника после покупки всех восьми. Продавая ниже 1187.5 мы будем “в минусе” (будет для нас затратно).

Теперь вернёмся к наше конфигурации 1С. Мы в регистр накопления “ТоварыНаСкладах” добавили два ресурса – количество и сумма. И это не случайно почему я так сделал. Обратите внимание, что средневзвешенная цена это ничто иное как:

СредневзвешеннаяЦена = СуммаИзНашегоРегистра / КоличествоИзНашегоРегистра

Т.е. все в нашем регистре уже есть чтобы найти средневзвешенную цену каждого товара. А что делать с продажей, давайте посмотрим на нашу обработку проведения при реализации. Скорее всего там окажется как-то так:

И действительно – нужно списывать суммовые остатки не по цене продажи, а по средневзвешенной цене. Тогда после реализации будут правильные остатки и оставшегося товара.

На самом деле учет средневзвешенной цены не единственный. Есть ещё учет, когда сначала списываются более ранее приобретенные товары или есть учёт, когда сначала списываются более поздние приобретенные товары. Эти способы называются соответственно FIFO и LIFO. Какой способ выбрать зависит от той или иной политики определенной организации и решается управляющим комитетом компании. Но для нашей конфигурации я волевым решением принял способ по средневзвешенной цене.

Но как же нам тут посчитать эту цену с точки зрения 1С? Делаем это так:

И чуть далее самое главное так:

Теперь сначала добавим ещё один документ покупки чайников (где мы покупаем 3 штуки по 1500). Далее изменим документ реализации чайников, указав там, что продали мы не 2 штуки, а 6 штук. Проведем его и проверим содержимое регистра, что с чайниками теперь всё ок:

Да, всё как и хотели – купили 5 по 1000, ещё докупили 3 по 1500 и продали 6 по 7125. Ещё раз заметьте, что продали мы не на сумму 7125 руб., т.к. продали мы на самом деле на сумму 1200 (это цена продажи) * 6 = 7200 руб., а продали мы по себестоимости 7125 руб. 7125 – это себестоимость проданных товаров, т.е. за сколько они нам обошлись при покупке (разумеется по средневзвешенной цене).

Внимание! Здесь документ, где мы докупаем ещё 3 чайника, должен стоять по времени после первого документа покупки и перед документом продажи.

Давайте разбираться что тут происходит.

Сначала мы создаём объект запроса и передаём в него параметры, по которому будем фильтровать результат:

Запрос = Новый Запрос;

Запрос.УстановитьПараметр(“ДатаО”, Новый Граница(Новый МоментВремени(ЭтотОбъект.Дата, ЭтотОбъект.Ссылка), ВидГраницы.Исключая));

Запрос.УстановитьПараметр(“Товар”, СтрТ.Товар);

Параметр ДатаО – это дата и время, на которое нам нужно получить остатки каждого товара. Казалось бы, давайте сюда просто напишем дату документа и всёго делов-то! Но нет, так неправильно. Дело в том, что пользователь может документ провести повторно (ну забыл он провёл его или нет или просто привык закрывать кнопкой “Провести и закрыть”, или что-то поменял и решил перепровести). Что тогда получится в этой казалось бы безобидной ситуации? А получится вот что – программа увидит дату самого документа (а как я уже сказал, документ уже и так проведен) и возьмёт момент времени ни до того как его провели, а сразу после этого момента времени – по-умолчанию). Т.е. дата одна и та же, но момент времени до проведения документа и после его проведения – это существенная разница! Ведь после проведения количественный остаток уже будет не 8 штук чайников, а за минусом того, сколько мы уже списали этим документом когда прошлый раз его проводили. Если бы мы сначала распровели документ (отменили проведение), а потом стали бы проводить заново, то такой проблемы не возникло бы. Но как я уже сказал, пользователь может повторно проводить уже проведенный документ. В этом случае программе нужно сказать, что мы исключаем момент времени самого документа. Делается это такой непростой конструкцией.

Второй параметр – это фильтр по Товару, ведь нам для каждого проводимого в документе товара нужно посчитать его себестоимость отдельно.

Сам запрос тоже стоит разобрать:

|ВЫБРАТЬ
| КоличествоОстаток,
| СуммаОстаток
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(&ДатаО)
|ГДЕ
| БытоваяТехника = &Товар

Когда мы в прошлый раз писали его в СКД, там было как-то похоже, только без знака “|” (вертикальная черта). Дело в том, что в СКД, в предназначенное для запроса поле, ничего писать иное не предполагается, а в языке 1С в кавычках указываются текстовые константы и чтобы их можно было переносить по строкам, нам придётся сообщить о своём намерении платформе 1С и ставить этот служебный знак вначале строки.

Запросы 1С состоят из двух обязательных частей, которые выглядят так:

ВЫБРАТЬ ПоляКоторыеНужноВыбрать ИЗ ОткудаВыбратьЭтиПоля

К тексту запроса можно добавить условие, как это сделано у меня:

ГДЕ БытоваяТехника = &Товар

Вообще по строкам принято переносить исключительно для более лёгкого понимания самого программиста, чтобы он быстро мог вспомнить что там написал или понять что там написал другой программист. Чем легче читать код или текст запросов, тем быстрее можно решить поставленную задачу.

Таблица откуда брать тоже похожа, только вот таблица немного другая и параметры для неё другие. Помните, в СКД мы брали таблицу ОстаткиИОбороты, а тут только Остатки. Соответственно, у остатков без оборотов нет периода, а есть только одна дата, на которую брать эти самые остатки.

КоличествоОстаток – Внимательный читатель скажет,- Слушай автор, откуда взялось слово Остаток у этого поля? Ведь поле мы называли просто “Количество”.- И этот читатель будет прав – мы не создавали действительно такого поля, это поле создала платформа 1С когда увидела в модификаторе регистра накопления конструкцию “.Остатки(???)”. Далее платформа увидело поле “Количество” и просто, что называется тупо, прибавила к этому слову слово “Остатки” и получилось новое поле “КоличествоОстатки”. Если вы внимательно просмотрели таблицу прошлого урока, то увидели, что и с таблице ОстаткиИОбороты в СКД она сделала тоже самое:

Идём далее.

Выборка = Запрос.Выполнить().Выбрать() – это примерно тоже самое, что мы на прошлом уроке нажимали на кнопку “Сформировать” в отчете. По этой команде анализируется текст запроса, и если он без ошибок, то происходит обращение к базе данных и получение результата. Метод “Выбрать()” говорит о том, что мы хотим получить результат в виде итератора, а не какой-то таблицы.

Выборка.Следующий() – Делает попытку спозиционироваться в итератора на строке результата. Если это удалось (ещё перебрали все строки результата или вообще есть хотя бы одна строка результата), то возвращается ИСТИНА. Тут этими условиями мы сообщаем, что если такое позиционирование не удалось, то значит таких товаров на складах, которые мы хотим реализовать, нет вообще на остатках.

Второе условие проверяет, мол это очень хорошо, что остатки всё-таки есть, но хорошо бы их число было бы больше или равно тому, что мы хотим реализовать. Если это не так, то это тоже ошибка – нельзя списать то, чего у нас нет.

В завершении мы просто меняем сумму списания с учетом результата запроса, т.е. получаем себестоимость и умножаем её на количество реализованного товара:

Запись.Сумма = Выборка.СуммаОстаток / Выборка.КоличествоОстаток * СтрТ.Количество; // ТЕПЕРЬ ПРАВИЛЬНО

Задание по уроку:

1. Сделайте полностью функционал по учету мелочевки с соответствующими документами, регистром остатков и обработками проведения.

2. В рабочей среде создайте документы и внесите необходимый товар касаемый мелочевки.

3. Создайте отчет, который будет отражать остатки по этому регистру.

Если всё получилось как нужно – молодцы! Если нет, давайте разберёмся что не так.

Программирование 1С. Урок 6

Продолжаем вникать в 1С и теперь настало время поговорить о коде 1С и о том как он устроен, о его синтаксисе. Вы уже успели посмотреть как работает то или иное действие в документах и вот стоит слегка разобраться в подробностях.

Программный код можно разместить в разных местах 1С и для каждого существует своё назначение, а разделение носит сугубо условный характер. Код разносится по различным модулям исключительно для логической организации работы и зависит только от степени фантазии программистов его делающих. Однако, есть некоторые негласные правила, о которых поговорим позже.

Общий модуль. Код, который размещается в общих модулях условно виден из всех остальных модулях, справочников, документов, прочих объектов. Почему условно будет понятно далее.

И если дать ему имя, то будет как-то так:

Модуль объекта. С этим модулем мы столкнулись когда делали обработку проведения документов. Программный код условно виден из модуля того объекта, которому принадлежит.

Модуль формы. С этим модулем мы столкнулись, когда делали подсчет суммы как произведения цены на количество в табличной части документа поступления товаров/услуг. Условно виден из той формы, в которой он расположен.

Каждый модуль состоит из программного кода, но не просто линейного от начала модуля и до конца, а структурированного – модуль состоит из процедур и функций, комментариев и ряда служебных слов, о которых говорить пока рано. Выглядит в общем примерно так:

Тут есть примерно всё из перечисленного. Т.е. как вы понимаете, программный код располагается внутри модуля, но не просто где попало, а внутри процедур и функций.

Функции – части программного кода, предназначенные для выполнения каких-либо задач и возвращающие какой либо результат. Например, типичные функции – расчет максимального или минимального значения среди множества. В математике функции аналогичны – например, расчет синуса или косинуса. Но главное – это возврат какого-либо результата.

Процедуры – части программного кода, предназначенные для выполнения каких-либо задач или расчетов, но не предназначенные для возврата какого-либо результата. Отличает процедуры от функций только одно, они не могут возвращать никакой результат.

В примере выше, функция МояПерваяФункция() возвращает сумму значений, находящихся в двух переменных. В результате выполнения переменная ЗначениеМоейПервойФункции будет равно числу 9.

Когда говорят о функции или процедуре принято после её наименования писать две круглые скобки без параметров – открывающую и закрывающую. Это позволяет сразу понять, что речь идет не по какой-то переменной МояПерваяФункция, а именно о функции МояПерваяФукнция(). К сожалению этим способом нельзя отличить функцию от процедуры, по этому об этом говорят явно.

Процедуры и функции начинаются с ключевого слова “Процедура” или “Функция”, далее следует её наименование и список параметров, которые заключены в круглые скобки. Заканчивается определение процедур и функции соответствующими ключевыми словами “КонецПроцедуры” и “КонецФункции”. Начало процедуры или функции ещё принято называть её определением (в различных языках программирования, не только в 1С).

Иногда могут сказать, что функция была объявлена, но это не совсем верная терминология, ну в смысле, объявил функцию. Дело в том, что во многих других языках определение и объявление функций и процедур это разные конструкции кода, несущие вполне самостоятельное значение и не имеющих между собой ничего общего, т.е. это разные термины с различным смыслом.

Процедуры и функции могут быть стандартными (встроенными) уже самой платформой 1С, например, максимум из числе:

Т.е. я нигде не определял функции Макс(), но программа знает что нужно делать при её вызове – посчитать максимальное значение среди параметров.

А могут быть и пользовательскими, пардон, созданными программистами (но это всё равно в терминологии – пользовательские). МояПерваяФункция() и МояПерваяПроцедура() – это типичный пример пользовательской функции и процедуры.

Внутри пользовательских процедур и функций, или как и называют без слова “пользовательские”, а просто – процедур и функций, располагаются выражения.

Выражение – часть программного кода, несущего вполне самостоятельное действие и является близким аналогом математического выражения. Выражения разделяются между собой знаком “;” (точка с запятой). Например, в моей первой процедуре два выражения. Выражения в процедурах и функциях выполняются от начала и до конца, если не встречают на своём пути условий ограничивающих их выполнение. Такое выполнение иногда называют “сверху вниз” и оно принято во всех языках программирования. Выражения состоят из логически, математически или конкатенально организованных действий из функций, процедур, переменных и констант. Выражение оформляется следующим образом:

Если выражение предполагает наличие результата – указывается переменная, куда будет помещен результат, затем знак “=” (знак равенства) , а после него формула.

Если выражение не предполагает наличие результата – указывается необходимая процедура вызова.

Переменная – аналог математической переменной. Предназначена для хранения какого-либо значения. Значением могут выступать число, строка, дата, объект и т.п. Каждая переменная содержит в себе тип того значения, которое хранит. Например:

МояПеременная1 = 4; // Хранит число, следовательно у неё тип “Число”

МояПеременная2 = “Моя какая-то строка”; // Хранит строку, следовательно у тип “Строка”

МояПеременная3 = Истина; // Хранит значение только Истина или Ложь, следовательно у неё тип “Булево”

Задание значения переменной строго определенным значением, как в этих примерах, называется инициализацией переменной.

Существует ещё большое множество типов, которые может принимать переменная. Однако можно выделить среди них несколько стандартных (имеется ввиду для разных языков программирования):

Булево – принимает только одно из двух значений ИСТИНА или ЛОЖЬ. Со значением булево доступны логическое умножение, сложение, а также отрицание (моя статья “Программирование вообще с нуля“), например:

КакойтоРезультат = НЕ ЭтоЗабалансовыйСчет И ЭтоСчетТоваров

Мы уже делали операции с булево:

Число – принимает числовое значение пригодное для выполнения математических операций, например:

ЧислоТочекНаЭкране = 1920 * РазмерМонитораПоИгрек + РазмерМонитораПоИкс

Мы уже делали операции с числами:

Строка – принимает текстовую информацию. Строки можно складывать между собой, но это не математическое сложение, а строковое (сложение строк), которое ещё иногда называют “конкатенация”.

Мы уже делали конкатенацию:

Строковые переменные можно переносить по строкам, извините за тавтологию, но вы наверно уже обратили внимание как я это делал; правильно, нужно просто вначале строки поставить знак “|” (вертикальная черта):

Эта вертикальная черта будет проигнорирована платформой, а строки будут представлены их так, будто всё написано без переноса на новую строку (будто всё было написано в одну строку).

Строку можно сложить с числом, тогда будет выполнена конкатенация, при этом число будет предварительно представлено тоже строкой. Для этого перед числом должна конкатенироваться строка или оно принудительно должно быть преобразовано в строку:

Результат = 95 + ” кг”; // НЕПРАВИЛЬНО! Будет ошибка

Результат = “”+95+” кг”; // ПРАВИЛЬНО! Ошибки не будет, т.к. “” – это тоже строка и она конкатенируется к числу

Результат = Строка(95)+ ” кг”; // ПРАВИЛЬНО! Ошибки не будет, т.к. выполнена встроенная в платформу функция Строка() преобразующая параметр к строке.

Дата – Этот тип переменных индивидуальное свойство 1С. Это вполне самостоятельный тип переменной, однако я решил указать его тоже. Дело в том, что во многих других языках программирования, дата – это просто строка представленная в определенном формате, но в 1С – это отдельный тип.

Неопределено – переменная в специальной форме значения, тип которого не был определен. Если кто знает другие языки программирования – это некий аналог значения null из Java или NULL из Си. Для тех, кто не знает других языков, для простоты можно сказать, что значение “неопределено” используется тогда, когда нужно объявить в коде переменную без какого-либо значения (не число, не строка или ещё что-то). Такое нужно для того, чтобы по итогам выполнения кода после такой инициализации, стало понятно, выполнился код по определению этой переменной или по каким-то причинам этого не произошло. С этой переменной нельзя производить никакие действия, кроме присвоения и сравнения.

С переменными всех типов можно производить следующие действия в выражениях:

  • Присвоение значения (инициализация)
  • Сравнение (меньше, больше, равно, неравно и т.д.)

Вообще, работа с переменными сводится в два этапа – сначала она объявляется, затем используется. Использовать необъявленную переменную нельзя.

Иногда при выполнении кода, как я только что сказал, нужно ограничивать выполнение той или иной его части. Для этого в программный код встраиваются условия.

Мы уже использовали условия в документе реализации:

Структура условий выглядит так:

Если ТутКакоетоУсловие Тогда

// Тут что-то выполняется

ИначеЕсли ТутДругоеКакоетоУсловие Тогда

// Тут что-то другое выполняется

ИначеЕсли ТутЕщёДругоеКакоетоУсловие Тогда

// Тут что-то ещё другое выполняется

………………… и так ещё сколько угодно раз ………..

Иначе

// Тут выполняется в том случае, если никакое из условий выше так и не выполнилось

КонецЕсли;

С условиями вопросов, по идее, быть не должно, но если всё же появились, то задавайте в комментах.

Если вы на прошлых уроках следовали рекомендации и прочитали мою статьи “Программирование вообще с нуля“, то уже знакомы, что в любом языке программирования есть циклы. Видов циклов в 1С три, два из них (тип 2 и тип 3) мы уже использовали.

Тип 1:

Для Н = 1 ПО 25 Цикл

// Что-то тут делать 25 раз. При каждой итерации переменная Н будет увеличиваться на 1.

КонецЦикла;

Тип 2:

Для СтрТ ИЗ НекаяТаблицаЗначенийИлиМассивИлиДругойИтератор Цикл

// Что-то тут делать пока удаётся получить в переменную СтрТ значение очередной строки из переменной НекаяТаблицаЗначений , хранящей объект ТаблицаЗначений.

КонецЦикла;

Тип 3:

Пока Выборка.Следующий() Цикл

// Тут что-то делать пока результат итерации равен ИСТИНА

КонецЦикла;

Как вы наверно уже успели заметить, я обычный текст внутри кода пишу после двух правых слэшей:

// Тут какой-то текст не на языке программирования, а по-русски

Так в 1С объявляются комментарии. Как можно понять, всё что после // и до конца строки, может быть любой текст. Платформа 1С его просто будет игнорировать. Комментарии нужны чтобы потом ускорить понимание того, что вы написали в той или иной части кода, ведь сам код может быть очень сложен. Но если описать простым языком что он делает и когда используется, то через полгода возвратившись к нему, проблем с пониманием и вспоминанием скорее всего не возникнет.

Задание по уроку:

1. Самостоятельно найдите в поисковых системах функции работы с числом и строками, такими как Число(), Строка(), Сред(), Лев(), Прав(), ВРег(), НРег(), СтрНайти().

2. Самостоятельно найдите способы преобразования даты в строку и наоборот – из строки в дату.

3. В справочник БытоваяТехника добавьте реквизит “Бренд”, указывающий фирму производителя со ссылкой на новый справочник “ПроизводителиТехники” и заполните этот реквизит для уже внесенных данных:

Т.е. убрать из названия фирму производителя и сделать это отдельным реквизитом:

Если всё получилось как нужно – молодцы! Если нет, давайте разберёмся что не так.

Начало программирования вообще с нуля. Часть 3. Бинарные данные.

В прошлой части мы начали говорить о бинарных данных. Давайте немного углубимся в этот вопрос. Если рассуждать по честному, то вся информация в компьютере – это бинарные данные. Отличается только их смысл и представление. Давайте откроем некий файл для просмотра и вроде как он содержит обычный текст:

Рис.1

Рис.1

Теперь немного изменим представление этого же файла:

Рис.2

Рис.2

А теперь ещё поменяем представление на другое:

Рис.3

Рис.3

В средней части, как вы возможно уже читали предыдущую часть из серии “Начало программирования вообще с нуля” и догадались, хранится байтовое значение представленных с права символов. Т.е. бинарные данные. Весь представленный текст – это 115 байт информации.

Самая левая часть – это колонка с адресом, далее идут две средние колонки двоичных данных по 8 байт (всего в строке 16 байт), а справа их представление. Как можно заметить, какое бы представление не было, бинарные данные одни и те же. И это не удивительно, ведь они и есть истинная исходная информация. То, как мы хотим её видеть, в виде чисел шестнадцатиричной системы, или текстом в разных видах, вопрос другой, на самом деле данные одни и те же.

Теперь вопрос касаемый представления. Давайте посмотрим на все это немного подробнее. Заметьте, везде пробел представлен числом 20h, цифра 2 в годе 2023, представлена числом 32h. Ещё один момент, на который нужно обратить внимание – это то, что в представлении на рис.1 и рис.2 весь английский текст и цифры выглядят одинаково, а весь русский текст по разному. Дело в том, что тут есть одно правило. Все символы латинского алфавита, цифры, знаки препинания, пробел и ещё некоторый набор символов являются представлением байта со значением меньшим 128, т.е. байты 00-7Fh, и за каждым значением всегда закреплен определенный символ. Диапазон 80-FFh – это пользовательские символы представляемые определенной кодировкой (но есть небольшое исключение). Казалось бы, зачем было так делать?

Когда-то давным давно, когда каждый день вызывал перерождение компьютерной идеологии, большая часть информации вносилась на английском языке. Однако, в процессе интеграции компьютеров по всему миру, его стали использовать для отображения текстов на русском, немецком, французском, японском и т.д. языках. Сначала, до появления WIndows, за то, в какой национальной среде какие 2(!) языка использовать (английский и ещё какой) отвечали настройки операционной системы. Затем, когда стали вдруг появляться тексты сразу на нескольких языках (на одном рабочем месте), стали использовать отдельные символы. Ну, например, 00-7Fh – это всегда английские, 80-FFh – это как бы русские, но есть ещё несколько символов из испанского, такие, например, как ò (ударная о) или è (ударная е), также туда были добавлены некоторые буквы норвежского языка, например, å, и т.п. В общем, с горем по полам, как-то писались тексты. Проблемно стало, когда в языки стали включать иероглифы, которых, как мы понимаем, несколько больше, чем все алфавиты романской группы и кириллицы. Нужно было что-то менять. Стали придумываться разные кодировки, но беда была в том, что либо туда что-то не попадало, как кодировка ASCII или ANSI, либо туда попадало всё, но текст стал занимать место на дисках в несколько раз больше. В то время дисковые накопители обладали размером в сотни тысяч раз меньшим, по этому такое расточительное хранение текста считалось недопустимым. Со временем диски стали лавинно увеличиваться в размерах, а программисты искали методы для более эффективного хранения текстовой информации. На стыке одного и другого и произошли радикальные изменения. Но история об этом хранится, и теперь от старых кодировок быстро не отделаться, т.к. много текста хранится в них. Также есть старые операционные системы или микрокомпьютеры, где не нужно хранить текст, например, на китайском, а достаточно хранить на английском. Например, моя посудомоечная машина Ariston может вообще показывать только цифры и буквы P и E, зачем управляющей ей операционной системе хранить текст в современной кодировке? Кстати и стиралка тоже лексиконом не блещет)). Наиболее же перспективной кодировкой на 2023 год является кодировка UTF-8, она позволяет хранить текст одновременно на всех алфавитах (в т.ч. и иероглифы), даже например такие как Ѭ, Ѧ. Это всё потому, что под каждый символ национального языка, выделяется памяти больше одного байта. Также на правильное представление влияет не только в какой кодировке хранится текст, но и какая кодовая таблица используется. Т.е. кодировка из текстовой строки получает набор кодов символов, вторая таблица коды символов ассоциирует с определенным знаком/символом/буквой/иероглифом. Кодовая таблица сейчас используется unicode.

По этому, говоря о данных находящихся в компьютерах, принято иногда характеризовать о каких данных идет речь, о бинарных или нет. В итоге, например, нельзя просто сказать “Пришли мне бинарные данные надписи Привет, мир!”, потому что она содержит текст на национальном языке и не понятно в какой кодировке тебе их прислать. В кодировке ASCII это будут вот такие бинарные данные:

В прошлой части мы начали говорить о бинарных данных. Давайте немного углубимся в этот вопрос. Если рассуждать по честному, то вся информация в компьютере - это бинарные данные.-4

В кодировке UTF-8 это будут уже такие бинарные данные:

В прошлой части мы начали говорить о бинарных данных. Давайте немного углубимся в этот вопрос. Если рассуждать по честному, то вся информация в компьютере - это бинарные данные.-5

Как видите строка UTF-8 занимает куда больше места, хотя это тот же самый текст “Привет мир”. Однако, попробуем закодировать ещё и надпись “Hello world”, в ASCII это будет:

В прошлой части мы начали говорить о бинарных данных. Давайте немного углубимся в этот вопрос. Если рассуждать по честному, то вся информация в компьютере - это бинарные данные.-6

а в UTF-8:

В прошлой части мы начали говорить о бинарных данных. Давайте немного углубимся в этот вопрос. Если рассуждать по честному, то вся информация в компьютере - это бинарные данные.-7

Видно, что последовательность бинарных данных для текста “Hello world” одинаковая 48 65 6C 6C 6F 20 77 6F 72 6C 64. Каждому байту соответствует символ, что не скажешь о русских буквах. Получается, что если текст содержит только латинские символы, знаки препинания, цифры (это все символы с кодом меньшим 80h), то количество байт, требуемых для хранения такого текста равно количеству символов. Если текст содержит символы на национальных языках, то количество байт для хранения требуется больше.

С хранением строк должно быть немного понятно, а что с хранением в компьютере чисел. Дело в том, что как мы уже знаем, в одном байте можно хранить только целые числа от нуля до 255, а в двух байтах (по законам математики) от нуля до 256*256-1 = 65536, в 4-х байтах от нуля до 256*256*256*256-1=4294967296 и т.д.

Но мы знаем, что числа бывают отрицательными, как быть с этим? Здесь мы должны сначала определиться сколько мы будем выделять байт под число. После этого нам придётся пожертвовать одним (старшим) битом числа для определения знака. Если этот бит будет равен нулю, то это будет положительное число, а если 1, то отрицательное. Т.е. например, если нам нужно выделить переменную, которая будет хранить целое положительное число гарантированно не превышающее 255, то нам достаточно одного байта. Если же при этом число может быть отрицательным, то тогда уже без 1 старшего бита, т.е. только число не более 127 и не менее минус 127. Это может, например, использоваться тогда, когда вам нужно хранить проценты от 0 до 100% или от -100% до +100%, да мало ли ещё для чего может быть использован такой небольшой интервал. Однако, что с бинарными данными числа? Рассмотрим, например, бинарный байт E5h. Какое число в нём хранится, минус 27 (-27) или плюс 229 (+229)? Ведь с точки зрения бинарных данных и то и это будет E5h. Здесь тоже, как и со строкой, необходимо знать заранее, что это за бинарные данные. Если байт хранит целое положительное число, то тогда это 229, а если целое знаковое число, то уже -27. Это всё потому, что у E5h ( равен 1110 0101b ) старший бит единица и для знаковых чисел этот бит интерпретируется как признак минуса, а для беззнаковых чисел он просто ещё один старший бит числа.

Однако, я уже сказал, что целые числа могут храниться не только в байтах, но и в словах (это термин обозначающий 2 байта подряд – WORD), двойных словах (4 байта – DWORD) и т.д. Давайте посмотрим на это же число 229, если хранится в 2-х байтах. Бинарные данные тогда для него будут такими:

00 E5

Но оно и понятно – вот они два байта, старший байт нули, т.к. для этого числа и одного байта хватает, а младший байт всё тот же E5h. Однако, при хранении этого числа в двух байтах, старший бит (15-й по счёту) никогда не будет единицей – старший же байт целиком ноль. По этому становится не важным, перед нами 2 байтовое число знаковое или беззнаковое, оно всегда будет представлено как +229. Чтобы оно стало вдруг минус 27, бинарные данные должны быть такими:

FF E5

Но опять-таки это правило будет работать только для чисел не превышающих 2^15 (2 байта это 16 бит, но без знакового бита – 15). Как только число будет больше, уже опять нужно заранее знать знаковое там целое число или беззнаковое.

Из этого примера должно стать ясно, что в компьютере бинарные данные – это просто набор байт. То, чем это является на самом деле, текст, картинка, видео, файл экселя, файлы каких-то программ, решать пользователю, системе и прикладным программам, ну и конечно же программисту; они должны знать какой смысл этих бинарных данных, с которыми они работают.

В связи с этим во многих языках программирования чтобы задать переменную необходимо явно указать, что это за переменная – строка, байт, целое число под которое выделено 2 байта, 4 байта или даже 8 байт, а может это вообще вещественно число (число с дробной частью). Также, если это целое число, нужно указать есть ли у него знак или его нет. Исключение составляют вещественных числа – для них признак знака не указывается, т.к. физически сложно представить задачи, где нужно хранить дробное только положительное число. В связи с этим есть примерный ориентир при объявлении переменных:

byte a; // выделяется 1 байт, хранит целое число беззнаковое число

short int b; // выделяется 2 байта, хранит знаковое число

unsigned int c; // выделяется 2 байта, хранит беззнаковое число

int d; // выделяется 4 байта, хранит знаковое число

unsigned int e; // выделяется 4 байта, хранит знаковое число

long f; // выделяется 8 байт, хранит знаковое число

unsigned long g; // выделяется 8 байт, хранит беззнаковое число

long long h; // выделяется 16 байт,…

float i; // выделяется 4 байта, хранит вещественное число

double j; // выделяется 8 байт, хранит вещественное число

Хотя некоторые современные микропроцессоры поддерживают знаковый байт, компиляторы делать этого не позволяют, т.к. этот формат считается устаревшим и слишком специфическим.

Иногда для старых процессоров или процессоров для микроустройств, концепция немного изменена, особенно если процессор 32-битный или 16-битный. Там под int выделяться может только 2 байта, а под long – 4. Но обычно такая нестыковка проблем не вызывает, т.к. любой современный компилятор при необходимости может сообщить сколько же он будет выделять памяти под ту или иную переменную.

Со строками не так всё однозначно. Если программист захочет узнать сколько же байт памяти занимает у него в строке, то пока он не выгрузит эту строку в бинарные данные, не сможет этого подсчитать. Опять-таки за счет того, что строка может быть в разной кодировке – нужно сначала раскодировать строку в бинарные данные, а потом уже считать.

Существует ещё миллионы различных представлений бинарных данных, кроме строк, тут всё зависит только от того, какой в них был первоначальный смысл. Например, бинарные данные:

65 65 65 65

Что это? Это строка из 4-х символов “eeee”, это беззнаковое число int равное 1701143909, а может это программист тут хранит картинку 2 на 2 точки и 65h – это оттенок серого каждой точки? А может это часть сэмпла какого-то музыкального произведения, а может это исполняемый код процессора? Если заранее это не известно, для обычного читателя этих байт – это просто бинарные данные.

Начало программирования вообще с нуля. Часть 4. Логика.

...Люба повернулась к нему и произнесла

– Сергей, так ты сказал мне неправду?

– Нет, я сказал тебе ложь.- После этих слов она пренебрежительно отмерила его взглядом и не произнося ни слова, ушла прочь.

Однако в компьютерах такое вряд ли могло быть, ведь там есть только два состояния – истина или ложь, и в теории никогда не бывает неправды, сейчас я это объясню.

Ранее мы уже рассмотрели этот вариант, что бит со значением 0 (ноль) – это ложь, а бит со значением 1 – это истина.

Кстати, чтобы не путать букву “О” и цифру “0” (ноль), ноль когда-то давно выглядел вот так Ø (перечеркнутый ноль) и это действительно было удобно, ведь это два разных символа, и иногда шрифт такой, что не сложно их спутать. Особенно, когда речь идёт о так называемых Captcha – кодах из букв и цифр, которые нужно пользователю ввести, чтобы “подтвердить”, что он человек. Мне кажется, этот символ незаслуженно пропал из обихода. Сейчас он используется крайне редко.

Итак, истина или ложь. Например, я хочу изложить состояние погоды вчера и сегодня и говорю,- вчера шёл дождь, а сегодня дождь не идёт. Значит получается, что вчера наличие дождя – это истина, а сегодня наличие дождя – это ложь. Вроде тут всё должно быть понятно, мы одним битом можем описать был дождь или его не было, но это только если…я не соврал. Тогда возникает третье состояние – неопределенности, т.е. дождь-то на самом деле был, но я сказал, что его не было, а как моему собеседнику считать, всё-таки был дождь или нет? У людей такое происходит сплошь и рядом, а вот в вычислительных системах крайне редко. Человек подвержен воле, а компьютер – электромагнитным всплескам, и то и другое влияет на результат, но если в компьютерах это предусмотрели и сделали контроль ошибок и автоматическое их исправление, то у людей, скорее всего такого контроля нет. По этому, хоть вопрос и сложный, мы будем исходить из теории того, что в компьютерах есть только два состояния и никогда не бывает никакого другого.

Теперь рассмотрим обычную фразу “Я пойду на улицу гулять, только если не будет дождя, ну или хотя бы будет тепло”. С точки зрения компьютерной логики эта фраза бы выглядела так:

ЖеланиеИдтиГулять = НЕ Дождь ИЛИ Тепло

Тут есть вопросы по этой формуле? Со всем согласны и всё поняли? Если не так – пишите комменты разберём, это основы, которые нужно понимать с самого начала. В этой формуле есть два логических действия:

  • “НЕ” – знак отрицания, отрицание переменной стоящей после него, т.е. если переменная была равна 0, то становится 1, и наоборот. Иногда называется инверсией аргумента, а операция – инвертированием.
  • “ИЛИ” – называется логическое сложение. Результат истина, если хотя бы одна из переменных стоящих слева или справа от него равна истине

Так, а можно ли записать это желание идти гулять как-то по другому? Конечно можно, ведь я мог сказать и по другому – Я пойду на улицу гулять, только если не будет дождя или будет не холодно”. Согласитесь, общий смысл совершенно такой же. Как такая фраза будет записано логической формулой?

ЖеланиеИдтиГулять = НЕ Дождь ИЛИ НЕ Холодно

Мы заменили наличие теплой погоды с истины на ложь, но поставили перед этим оператор “НЕ”, и вернули смысл этой части выражения. А можно ли ещё как-то сказать фразу с этим же смыслом? Да, можно и по другому – Я не пойду гулять, если будет дождь и одновременно будет холодно. Смотрите, я сохранил общий смысл фразы, но аргументы формулы изменились полностью:

НежеланиеИдтиГулять = Дождь И Холодно

Однако, мы не знаем, что такой за результат “Нежелание”, у нас должно быть желание, поэтому перефразируем – Я пойду гулять, только если не будет одновременно идти дождь и на улице холодно, т.е. фактически так:

ЖеланиеИдтиГулять = НЕ (Дождь И Холодно)

Мы просто переставили НЕ из левой части в правую, так можно делать даже и в математике:

-A = B

=>

A = -B

Не будем отвлекаться, в этой нашей формуле мы использовали новый оператор “И”:

  • “И” – называется логическое умножение. Результат истина только если оба аргумента (слева и справа) будут истина, в ином случае значение будет ложь.

Из этих трех логических операторов И, ИЛИ, НЕ состоит вся компьютерная логика. В зарубежной литературе они называются аналогично – AND, OR, NOT.

В различных языках программирования эти действия используются постоянно, на них построены все результаты сравнения и условия. Например, в языке Си эти операторы записываются специальными знаками &, |, !, например:

C = A & B;

D = A | B;

E = !A;

, а в языке 1С – прямо по-русски:

ПрибалятьКСуммеНашихОстатков = НЕ СчетЗабалансовый И ЭтоУчетТоваров;

Мы помним из младших классов математики, что у вычислительных операций есть приоритет. Сначала производятся все умножения и деления, а затем вычитания и сложения, но весь этот приоритет выполняется с учетом скобок (если они есть). В логических операциях как-то примерно так, но немного по другому. Скобки имеют тот же смысл, что и в математики. Операции в скобках выполняются первыми (с учетом приоритета каждой операции внутри самих скобок). Самый высокий приоритет у операции отрицания, все операции “НЕ” выполняются в первую очередь (опять-таки с учетом скобок). Затем выполняются операции логического умножения, а уже после них логического сложения. Чтобы понять объясню “на пальцах”. Есть формула:

Результат = НЕ (Параметр2 И Параметр3 ИЛИ НЕ Параметр4) И Параметр5

Первым делом будет выполнена инверсия находящаяся внутри скобок:

НЕ Параметр4

Затем будет выполнено логическое умножение:

Параметр2 И Параметр3

После этого будет выполнено ИЛИ между ними. Затем будет инверсия находящегося этого промежуточного результата в скобках:

НЕ (…)

И лишь после этого инвертированный промежуточный результат будет логически умножен на Параметр5 и получен итоговый Результат.

В логических операциях есть метод упрощения, который может существенно улучшать читаемость логической формулы, особенно когда условий в ней очень много, например:

ЖеланиеИдтиГулять = (НЕ Дождь ИЛИ НЕ Холодно) ИЛИ НЕ (НЕ ДеньПослеЗарплаты ИЛИ НЕ ЭтоПятница)

Ну так когда же я захочу идти гулять при такой формуле??? Обязательно ли новое условие, что это должен быть день после зарплаты и это должна быть пятница, или я пойду в такие дни гулять при любой погоде, или нужно соблюдение всех перечисленных условий? Для этого нужно упростить хотя бы выражение чтобы не “ломать голову” сложными преобразованиями. Для этого нужно знать три простых метода преобразования:

Метод1: НЕ НЕ Параметр1 = Параметр1

Метод2: Параметр1 И Параметр2 = НЕ (НЕ Параметр1 ИЛИ НЕ Параметр2)

Метод3: Параметр1 ИЛИ Параметр2 = НЕ (НЕ Параметр1 И НЕ Параметр2)

Тогда можем преобразовать левую часть сначала по методу 2, а следом по методу 1:

(НЕ Дождь ИЛИ НЕ Холодно) = НЕ (Дождь И Холодно), т.е. левая часть говорит, что результат истина, если нет одновременно дождя и на улице холодно, т.е. если хотя бы нет дождя или хотя бы не холодно, то результат этой части истина.

Теперь вторая часть тоже по тем же методам:

НЕ (НЕ ДеньПослеЗарплаты ИЛИ НЕ ЭтоПятница) = (ДеньПослеЗарплаты И ЭтоПятница)

В результате получается:

ЖеланиеИдтиГулять = НЕ (Дождь И Холодно) ИЛИ (ДеньПослеЗарплаты И ЭтоПятница)

По-русски это будет звучать так: У меня будет пойти желание гулять, только если нет на улице одновременно дождя и холода независимо от дня зарплаты и дня недели, но могу и пойти гулять если это день после зарплаты и одновременно этот день выпадет на пятницу независимо от погоды. В ином случае желания гулять не возникнет. Операция “ИЛИ” между левой и правой частью как раз и делает языковое выражение словами “независимо” или словами “хотя бы”, т.е. раньше я говорил, что “ИЛИ” – это когда истина хотя бы один из аргументов слева или справа (независимо друг от друга, хотя бы один из них). Напоминаю, операция “И” – наоборот,- чтобы результат был истина, нужно чтобы оба аргумента были истина, это выражается формой русской речи “одновременно”, т.е. “результат истина, когда одновременно левая и правая части истина”.

Программирование 1С. Урок 7

Теперь можно открыть ещё одну занавесь. В прошлом уроке я сказал, что модули условно видны. Всё дело в том, что современное программирование всё более тесно связано с так называемой клиент-серверной моделью. Об этом я рассказываю ТУТ. В этом смысле 1С не исключение, по этому программист должен понять, какая часть его кода будет работать у пользователя на его персональном компьютере и какая часть кода будет работать на сервере. По этому, если вы делаете общий модуль, процедуры и функции которого будут общими для каких-то задач из разных областей вашей конфигурации, вы должны заранее определить будет этот модуль виден на клиенте, на сервере или и там и там. Однако, вы должны понимать, что все модули, которые имеют в своём определении “на клиенте”, будут выгружаться в пользовательскую среду на каждый компьютер, и это должно быть действительно оправдано с точки зрения оптимизации системы. В тоже время определение модуля “на сервере” тоже должно быть оправдано, чтобы пользовательский клиентский компьютер не гнал лишний траффик, например, только для того чтобы взять часть строки, выполняя это на сервере. Например следующий код:

Функция ПолучитьЛевыйСимволИзСтроки(НекаяСтрока)

Возврат Лев(НекаяСтрока, 1);

КонецФункции

Этот код совершенно нерационально делать на сервере, если вы будете вызывать его только с клиента. Однако, если и на сервере вам придётся выполнять эту функцию, то у вас не будет иного варианта, как сделать её на сервере, т.к. серверный код не может выполнять код, если он определен только как клиентский. Есть вариант конечно же и ещё третий вариант, но рациональность его условна и действует только в определенных случаях – это разместить в двух разных модулях (в серверном и клиентском) этот одинаковый код.

А вот такой код никогда не получится выполнить на клиенте:

Функция ПолучитьЛевыйСимволИзСтроки(НекаяСтрока)

Запрос = Новый Запрос;

// Как-то обрабатываем сам запрос или его результат

КонецФункции

И проблема здесь лишь одна – объект “Запрос” невозможно создать на клиенте, т.к. на клиентском компьютере нет возможности напрямую работать с базой данных.

Но это всё хорошо и красиво звучит в теории, а что с практикой, вы резонно можете сказать,- Автор, дай пример, где это использовать в нашей конфигурации, которую мы уже 7-й урок делаем!- Да пожалуйста!- ответил я.- Помните как мы считали сумму по строке в формах документов поступления товаров и реализации товаров? А делали мы это так:

Кстати, вы наверно внимательный слушатель курса и по этому заметили, что в модуле формы есть перед каждой процедурой и функцией ключевые слова “&НаКлиенте”, “&НаСервере”, а например, в модуле проведения документов их нет нигде. Всё дело в том, что в форме можно выполнять как клиентский код, так и серверный, только нужно сказать точно, где будет располагаться ваша процедура или функция, а в модуле объекта все пользовательские функции и процедуры выполняются на сервере.

Тут нужно сразу сказать, что всё не так однозначно. В серверных модулях 1С можно выполнить такую 100% клиентскую процедуру, как вывести сообщение пользователю. Не знаю точно, но это наверно единственная клиентская процедура, которую сервер транспортирует на клиента, причём только на того, который её исполняет. Т.е. если сделать вот так:

То будет вот так (всё нормально работает):

Так вот, отвлеклись, а теперь возвращаемся далее к коду. Мы видим, что эта процедура встречается в трёх видах документов – поступление мелочёвки, поступление товаров и услуг и реализации товаров и услуг. Эта процедура одинаковая для всех этих видов документа, так спрашивается, зачем нам её создавать аж три раза, если можно сделать одну в каком-нибудь общем модуле. Давайте так и сделаем. Кликните там, где я показывал это уже ранее и создайте новый общий модуль и при помощи ПКМ вызовите его свойства. Дайте ему имя “ОбщиеПроцедурыИФункцииКлиент” и укажите область видимости “Клиент”:

Флажка “Сервер” наоборот быть не должно, т.к. в нашей этой процедуре есть чисто клиентский объект формы, который так и называется “Объект” и гнать его на сервер не нужно (на сервере мы не будем как-то использовать форму объекта, да и не получится это сделать). Если вы всё же попытаетесь передать серверу то, что должно существовать как объект только на клиенте, то получите что-то вроде этого:

Т.е. в ошибке значится, что невозможно воспроизвести объект клиентской формы на сервере ввиду отсутствия такой возможности; но оно и понятно – кому на сервере форму показывать, соседним лампочкам в дата-центре? ))

Скопируем нашу процедуру из документа и вставим её в этом модуле:

Теперь её нужно немного доработать. Во первых, продолжение к разговору об условной видимости. В таком виде процедура не будет видна только из этого же модуля. Откуда-нибудь из другого места, из формы, из другого модуля, хоть на клиенте, хоть где, эта процедура будет невидимой. Чтобы она стала видимой нужно сделать вот так:

Т.е. обозначить её как экспортную процедуру. Это волшебное слово сразу сделает её видимой из любого клиентского модуля. Подчёркиваю – именно клиентского, т.к. мы в самом модуле флажок поставили только у области расположения “Клиент”.

Так, дорабатываем дальше. Дело в том, что в общем модуле платформа совершенно не понимает такие объекты как Элементы и Объект. Это свойства формы, а процедура в модуле абстрагирована от какого-либо объекта кроме самой конфигурации. По этому ссылку на объект формы нужно передать как параметр и кое-что поменять:

Как видите, я фактически только добавил параметр (в круглых скобках) и в трёх местах сделал родительский объект. Т.е. сказал платформе,- “Элементы” и “Объект” – это не самостоятельные свойства непойми чего, а это свойства объекта ОбъектФормы, переданного в качестве параметра.

Сам модуль формы тоже изменим до вот такого вида (эта процедура в этом модуле формы больше нам не нужна, теперь есть общая):

Перезапустим и проверим. Для того чтобы полностью убедиться в праведности нашего пути, закройте рабочую среду, поставьте курсор на указанную ниже строку и нажмите функциональную кнопку F9. Должна слева в этой строке на полях появиться вот такая вот здоровенная точка:

Теперь запустите 1С. НО(!!!!) не как обычно, а вот так:

После этого запустится казало бы самая обычная среда, но только она будем отлавливать момент, пока функционал тем или иным образом не окажется в этой отмеченной строке. После этого платформа 1С поставит на паузу все свои действия и переведет указатель. Для того чтобы выполнение оказалось тут, что нужно сделать?- Правильно, зайти в документ поступления товаров и стереть с количества товара число и поставить его же снова (ну это как бы мы таким образом число поменяли на другое, для системы это всё равно событие изменение реквизита). Как только введете ENTER или кликните по другому полю, платформа 1С автоматически возвратит вас в конфигуратор (не закрывая рабочей среды, а только приостановив его) на эту самую строку, и стрелкой поверх нашего кружка укажет это:

Это будет означать, что выполнение программы действительно оказалось именно здесь. Там мы совершенно случайно познакомились ещё и с таким мощным инструментом 1С, как отладка. Теперь можно продолжить всё-таки доделать программе и завершить самой алгоритм, для этого нужно нажать функциональную клавишу F5, либо прямо прервать работу рабочей среды (ну мало ли мы что-то страшное написали и во чтобы то ни стало нужно всё остановить), тут надо будет пойти в меню, либо нажать Shift+F5:

Кстати, продолжить выполнять можно и по одному выражению, для этого нужно воспользоваться клавишами F10 и F11 (это тоже как и F10, только будет “входить” внутрь вызываемых процедур и функций,- тут проще сравнить и посмотреть разницу между ними воочию, чем долго объяснять)) ).

Теперь, когда мы знаем что такое отладка, давайте добавим в документ поступления товаров и услуг ещё два стандартные процедуры – ПередЗаписью и ПриЗаписи:

Поставьте в конце каждой процедуры точку останова, запустите рабочую среду в режиме отладки на нажмите кнопку “Провести и закрыть”. Нажимая F5, посмотрите внимательно по каким точкам и в какой последовательности будет выполняться функционал – сначала вызывается процедура ПередЗаписью, затем ПослеЗаписи и только лишь после этого ОбработкаПроведения:

В такой последовательности проводятся все документы 1С, это специфика платформы. Кстати у справочников почти также, только у них нет возможности проведения и соответственно процедуры проведения, но ПередЗаписью и ПриЗаписи – есть. Из названия самих процедур можно узнать, что одно происходит до того как изменения объекта оказались в базе данных 1С, второе как раз после этого, но до проведения, а третье вызывается, когда уже с документом произведено всё, что касается записи, и теперь нужно сделать всё, что касаемо проведения.

Теперь немного коснёмся пользовательского интерфейса, т.е. того с чем пользователь взаимодействует. Опять возвращаемся к нашей сумме по строке в документах. Всё с ней вроде неплохо, кроме одного – сумма сейчас доступна для редактирования; взял, случайно кликнул туда уже после того как она посчитана и получится вот так:

Ну вот как такое может быть?- 3 на 1500 равно двум…Это не дело, хорошо бы сделать так, чтобы поле это было заблокировано от ввода данных. Сначала для этого нужно в графическом представлении формы вызвать свойство этого реквизита, запрятано это вот туда:

А реквизита за блокировку аж два:

Отключение доступности блокирует реквизит полностью и от копирования и изменения, а свойство “ТолькоПросмотр” блокирует реквизит только от изменения. В нашем случае более правильным будет указать, что реквизит только для просмотра:

Сделаем так и перезапустим 1С, проверим, что теперь кликнуть и изменить реквизит суммы уже не получится:

Задание по уроку:

1. Доработайте остальные формы документов для вычисления суммы при помощи нашей общей процедуры. Убедитесь при помощи отладчика, что это действительно так.

2. Добавьте в справочник “БытоваяТехника” ещё один реквизит и назовите его “СоставноеНаименование”. Сделайте так, чтобы при записи справочника этот реквизит заполнялся автоматически составными словами из наименования и в скобках бренд. Вот так:

3. Сделайте поле составного наименования доступным только для просмотра, т.к. оно должно формироваться автоматически и не предназначено для редактирования.

Если всё получилось как нужно – молодцы! Если нет, давайте разберёмся что не так.

El Vinto, 2023

Начало программирования вообще с нуля. Часть 5. Клиент и сервер.

В современном мире (2023 год) все приложения и программы, с которыми мы так или иначе сталкиваемся живут в определенном виртуальном поле, называемом клиент-серверной организацией. Даже если мы запускаем обычный калькулятор на нашем планшете и предназначен он только для простых арифметических операций, он всё равно находится в клиент-серверном пространстве, просто для него ещё не придумано управляющего сервера и он выступает только оффлайн клиентом, т.е. клиентом без взаимодействия с какими-либо ещё клиентами. Если рассматриваем приложения вроде какой-нибудь социальной сети или онлайн-магазина, да что говорить, самый обычный браузер на компьютере – это полноценная часть клиент-серверного пространства, в котором им отведена почётная роль клиента. Сервера находятся где-то далеко, может быть на другом конце света, а может быть в соседнем здании и обрабатывают запросы клиентов. Так устроено это взаимодействие простыми словами. С точки зрения рядового пользователя, это просто приложение, которому нужен интернет и которое с ним как-то взаимодействует. Но мы хотим узнать с точки зрения программирования, и по этому будем рассматривать их независимо друг от друга как совершенно разные части (называемые узлами) этой взаимодействующей системы. Иногда запросов от клиентов происходит так много, что сервера не справляются и тогда было введено новое слово в обиход – “Облако”. Облачные системы – это взаимодействующие между собой сервера, которые в равной степени и взаимозаменяемо могут обрабатывать запросы от множества клиентов в рамках единой задачи. Например, облачные хранилища позволяет обрабатывать запросы от клиентов по хранению каких-либо данных. Желающих хранить данные не на своём компьютере оказалось много, по этому отдельные сервера стали не справляться и их стали объединять в единые сети обмена информации и при этом размещать в разных уголках Земного шара. Так появились облачные хранилища. По этому когда вы отправляете очередную свою фотку в “Облако”, то где она физически будет находиться в мире никто не знает, кроме самой облачной системы. Может в России, может в Африке, а может и так, что часть фотки в Бразилии, а часть во Владивостоке. Облачное хранилище само перераспределяет нагрузку, находит оптимальные алгоритмы хранения и передачи данных в зависимости от спроса, и распределяет всё что в него поступает так, как считает в процессе расчета наиболее рациональным.

Получается, что клиенты и сервер выглядят так:

Когда речь заходит об облаке, это выглядит так:

Так вот, к чему это я…С точки зрения программирования, программист должен понимать где его функционал должен работать на сервере, а где на клиенте. Например, нужно вывести сообщение пользователю, что товара нет в онлайн-магазине. Где должен выполняться этот код, на клиенте или сервере? Оказывается, что для того чтобы это действительно работало, программист должен написать для выполнения на сервере определенный код, который вычислит, что товара больше нет, передать при очередном запросе клиента, что количество некого товара равно нулю. Затем должен написать на клиенте чтобы он с определенной периодичностью опрашивал сервер на предмет изменения количества того или иного товара, принимать количество, и если оно равно нулю, то выдавать на клиенте это сообщение. Т.е. программисту нужно написать одну программу на сервере для ответной реакции по запросу клиента, и другую программу работающую на каждом клиенте, которая опрашивает сервер, выводит сообщения, принимает вводимые данные будь то клики по экрану или адрес получателя, или ваш телефон для связи. Аналогично работают и различные социальные сети. Ваш планшет с определенной периодичностью опрашивает сервер на предмет того, нет ли для вас нового сообщения, в этот момент может заодно передаёт ваше сообщение для кого-то, опрашивает не появилась ли на различных каналах ещё одна новость, не загрузил ли кто новый видос на сервер. К счастью, если вы только начинающий программист, и работаете по этой специальности недавно, то вам не придётся делать программу и для клиента и для сервера, обычно новичков ставят только на клиент и дают документацию о том как нужно обращаться к серверу (так называемые API обмена). Подытоживая сказанное, программист должен чётко и хорошо понимать, что выполняется на сервере, а что на клиенте, в связи с этим и доступные методы, классы и т.п. могут работать в зависимости от того где выполняются, а достаточно часто и могут быть вообще уникальны, только для выполнения на сервере или только для выполнения на клиенте. Например, на клиенте онлайн-магазина нельзя обратиться напрямую к базе данных сервера, а на сервере нельзя вывести сообщение для пользователя.

В клиент серверном варианте есть один нюанс. Одно дело когда у вас приложение онлайн магазина или социальной сети, другое, когда открываете страницу в браузере. Нет, не подумайте чего плохого))), и то и другое действительно клиент-серверное взаимодействие…с точки зрения организации системы. Но с точки зрения программирования, совершенно разное. Дело в том, что приложение уже написано и опубликовано, вы его скачали из магазина приложений в законченном виде, и лишь иногда делаете обновления, когда сочтёте это нужным. Если речь идет о клиент-серверном взаимодействии через браузер, то у вас нет на вашем домашнем компьютере заранее кода сайта чтобы его запустить для обмена с сервером, по этому при каждом обращении к сайту, он сначала выгружает с сервера в ваш браузер некий программный код (называемый обычно скрипт) и запускает его, и вот после этого и происходит взаимодействие клиента и сервера для обмена. Именно по этому раньше распространялось так много вирусов именно через сайты, так как играли злую шутку несовершенство операционных систем, самих браузеров и анализаторов кода, который выполнялся. При появлении мобильных приложений, перед публикацией магазин приложений почти всегда сначала проверяет его на наличие вирусов, вредоносного кода, да и сам разработчик должен быть зарегистрированным в этом магазине и предоставить свои персональные данные, чтобы было с кого спросить. С сайтами так делать в большинстве случаев не получается, т.к. нет механизма достоверной проверки кода этих сайтов (они расположены не централизированно в каком-то магазине, например, в магазине каких-то сайтов, а разбросаны в разных частях света на разных серверах и разных странах с разной юрисдикцией).

В клиент-серверной организации обмена часто всё сводится к тому чтобы передать некую информацию с одного клиента на другого. И это не только работа социальных сетей. Да, обычный онлайн-магазин – это тоже отчасти передача с одного клиента на другого – вы сделали заказ, количество товара на складе уменьшилось, и каждому клиенту рассылается новый остаток после вашего взаимодействия. Иными словами, сервер выполняет роль вычислительного звена и арбитра, можно сказать важного посредника, который организовывает всю работу взаимодействия.

Должен тут же сказать, чтобы не вводить вас в заблуждение, что клиент-серверная организация хотя и является доминирующей в мире информационных технологий, но не является единственной. Погружаться в другие на этом этапе знакомства с ИТ нет, но для эрудиции скажу, – есть ещё так называемые системы “Точка-точка” или “Пир-ту-пир”, или “peer-to-peer”, или они же “p2p”, или они же “Пиринговые сети”. Это систему у которых нет серверов вообще. Они взаимодействуют исключительно на прямом обращении одного клиента к другому, хотя было равно сказать и обращении одного сервера к другому. Типичным примером таких систем являются торрент-клиенты. В схеме это выглядит так:

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

Клиент-серверная организация накладывает определенные правила, особенно если речь идет о взаимодействии вроде как в вашем браузере, когда вы открываете очередную страницу какого-то сайта. Дело в том, что все устройства пользователей разные, разные производители, разные комплектующие, или вообще настолько разные как iOs, Android и MS Windows, а браузер, как я только что сказал, отправляет клиенту код, который должен на нём выполняться. Определить точно не всегда удаётся ввиду того, что часто клиент скрывает достоверную и подробную информацию о своей системе ввиду информационной безопасности, а выполнить код на нём всё равно нужно. По этой причине часть выполнения была возложена на операционные системы, способные воспринимать одни и те же скрипты так, чтобы клиентский компьютер их понял, этот процесс известен ещё со времён языка Бейсик и называется трансляцией. Т.е. сервер отправляет каждому клиенту чаще всего один и тот же скрипт работающий по одинаковому алгоритму, а клиент его уже сам дополнительно анализирует и преобразует в тот код, который поддерживает его устройство. Такой подход называется мультиплатформенным, т.е. один код для разных платформ, по этому к счастью, программисту чаще всего не надо задумываться о том, какое же устройство будет конечным на клиенте, и сосредоточиться только на том функционале, который ему необходимо реализовать; конечное устройство само должно позаботиться о том чтобы правильно воспринять тот или иной скрипт.

Когда речь заходит о взаимодействии в сетях, не важно каких, пиринговых или клиент-серверных, чтобы компьютеры правильно понимали что за информацию они друг другу передают, сама передача должна осуществляться по определенным правилам, называемыми протоколами.

Здесь в терминологии есть путаница, сетью называют как физическую сеть (в виде проводов), логическую сеть, ту самую, которую мы называем интернетом, когда каждый компьютер имеет свой адрес, также называемый IP-адрес (айпи-адрес), и обращение идет по нему, и сетью ещё могут называть бесконечное количество виртуальных сетей, т.е. одних логических сетей внутри других логических сетей, например VPN-сети, пиринговые сети и т.п.

Протоколов придумано великое множество. Есть стандартные, а есть уникальные, придуманные программистами для определенных обменов. Например, есть протокол TCP, который обеспечивает выход компьютера в интернет, он стандартный и строго соответствует всегда одним и тем же правилам, по этому подключенный компьютер в интернет сразу знает как общаться с вашим провайдером или с мобильным оператором. Но есть протоколы, которые никак не стандартизованы, например различные онлайн-магазины, соц.сети. Для них обмен регламентирован только фантазией программистов организовывавших этот обмен. Однако и тут, если обменную систему разрабатывает не один программист, а целая команда, тоже потребуется вводить внутренние стандарты для этой самой команды, и ориентироваться на них. Это означает, что нельзя например взять клиентское приложение одной социальной сети, немного переделать его и оно заработает для другой социальной сети. Вероятность успеха такого подхода стремиться к нулю, и всё по тому, что протоколы обмена будут разными, придуманными своей командой разработки со своей спецификой и особенностями.

В соответствии с вышесказанным, программирование для клиента и для сервера имеет ряд отличий, а также для того и другого придуманы специальные языки программирования. Наиболее известные языки используемые для клиент-серверной организации:

Для клиента:

  • Java Android (только для устройств на базе Android)
  • Swift (только для систем на базе iOS)
  • Javascript (только для браузеров, но для любых устройств)
  • Kotlin (для Android)

Для сервера:

  • PHP
  • Java servlet
  • Perl
  • Asp

Такие языки как Си и Паскаль позволяют писать как серверное программное обеспечение, так и клиентское, но требует намного более высокой квалификации и опыта. С другой стороны, язык 1С, ввиду специфики самой платформы, позволяет писать код одновременно и для серверной части и для клиентской, при этом требует совершенно иной квалификации, чем программист Си или Паскаль, хотя сам код 1С обладает намного меньшей функциональностью.

Перечисленные языки для клиента так или иначе накладывают ограничения на то, на каком клиенте они будут выполнятся, например, на языке Java Android нельзя написать для устройств на iOS (нет таких компиляторов) и наоборот. Для Javascript нельзя скомпилировать ни для Android, ни для iOS, ни на Windows, но если на этих системах есть браузер, поддерживающий Javascript (а такие браузеры наверно сейчас все), то тогда можно этот код выполнять через этот браузер и на том и на этом устройстве, с той или иной операционной системой.

Подобных ограничений для серверов не бывает, т.к. сервер изначально настраивается на работу с тем или иным кодом (php, java servlet и т.д.) и программный код пишется под определенный транслятор или компилятор, который, как понимаете, изначально всегда известен. Т.е. программист на php сразу будет настраивать или выбирать свой сервер с установленным транслятором php, а например, программист на Java Servlet установит на сервере программу Tomcat. Сами эти языки способы делать практически одно и тоже в примерно равных требованиях к ресурсам, по этому, скорее, это дело вкуса и возможностей, на чём делать сервер.

Сам выбор языка каждый делает тоже по-своему. Я например, сторонник того, чтобы синтаксис что серверных языков, что клиентских был хотя бы чем то похож, по этому изначально выбрал Си-синтаксис подобные языки:

  • Сам язык Си
  • PHP
  • Java
  • Javascript

Они позволяют осуществлять различные программные фантазии как на серверах, так и на клиентах, и других языков я сторонюсь только по одной причине – уж больно они не похожи на Си, а часто бывает так, что на решение той или иной проблемы нужно время. Искать проблему одновременно и в серверном коде и клиентском происходит намного быстрее, если сам синтаксис языков похож. Тут нет равных языку 1С, в котором не просто один синтаксис и для клиента и для сервера, так это и есть один и тот же язык)). Плохо, что 1С требует отдельной платформы, да и сервера 1С пока ещё не бесплатные)).

El Vinto, 2023

Программирование 1С. Урок 8

Давайте продолжим делать нашу конфигу, пардон, конфигурацию. И теперь настало время посмотреть, а что у нас на экране происходит, а происходит вот что:

Т.е. иными словами – что-то не так с интерфейсом. Всё в кучу, и справочники, и документы, и отчеты. Так не пойдет. Интерфейс должен быть безупречен, по крайней мере мы должны стараться так делать. Если пользователь в таком виде откроет программу 1С, он будет мягко говоря опечален, ведь ему работать с этим каждый день. Давайте начнем приводить в удобный вид. Для этого на платформе 1С специальный объект, который называется “Подсистема”.

Давайте добавим две новых подсистемы вот так и дадим им имена “Справочники” и “Документы”:

Получится как-то так:

Обратите внимание, тут случайно можно одну подсистему поместить по иерархии внутрь другой, но должно быть так – обе корневые. Теперь откроем каждую и по очереди установим справочники в свою подсистему:

, а документы – в свою:

Перезапустим 1С и посмотрим что получается:

Согласитесь, теперь намного круче. Однако, платформа 1С позволяет пользовательский интерфейс ещё немного донастроить уже в режиме предприятия (в рабочей среде, а не в конфигураторе). Делается это тут:

Теперь пользуясь перетаскиванием мыши расставьте панели в таком порядке:

Нажмите “ОК” и посмотрите как получилось:

Совсем другое дело – так намного удобнее и лучше, но тоже не особо. Дело в том, что негласно принято так, что сначала в разделах должны следовать справочники, а потом документы, если они выделены одновременно в разных разделах. Т.е. нужно изменить порядок. Это уже настройки конфигурации, по этому кликните правой кнопкой мыши по самой конфигурации и выберите пункт касаемый командного интерфейса:

Пользуясь кнопками вверх-вниз расположите в нужном порядке:

Теперь выглядит ещё лучше:

Теперь вспомним как мы смотрели проведение по регистру товаров на складах. Правильно, открывали функции для технического специалиста и искали там наши проводки. Делать это не всегда удобно, особенно если мы работаем с конкретным документом. Хотелось бы как-то сразу никуда не переходя посмотреть какие проводки он создаёт. Сейчас мы сделаем некоторые манипуляции и посмотрим о чём я говорю.

Откройте форму документа ПоступлениеТоваровУслуг и перейдите на вкладку “Командный интерфейс”:

Откройте иерархию “Перейти” и посмотрите что там как раз наш регистр:

Помните, когда мы указывали, что наш документ ПоступлениеТоваровУслуг является регистратором регистра ТоварыНаСкладах? Вот, программа это помнит и понимает, что наверно вы захотите возможно включить этот регистр в командный интерфейс, но уже не всей конфигурации, а командный интерфейс именно этого вида документов. Включите видимость и перезайдите в 1С:

Открыв документ видим что-то новое:

И это не что иное, что мы собственно и хотели – записи регистра, созданные именно этим документом:

Задание по уроку:

1. Сделайте раздел командного интерфейса для отчетов и расположите там наш отчет “Товары на складах”

2. Добавьте командный интерфейс с регистром ТоварыНаСкладах для документа РеализацияТоваров.

3. Создайте два новый справочника ЕдиницыИзмерения и ПродуктыПитания. У продуктов питания добавьте реквизит ЕдиницаИзмерения:

Включите их командный интерфейс справочников. Создайте две единицы измерения “шт” и “кг”. Создайте несколько позиций продуктов питания, указав в какой она измеряется единице измерения:

Сделайте вид документа “ПоступленияПродуктовПитания” и внесите несколько документов в учет, что-то вроде такого:

Если всё получилось как нужно – молодцы! Если нет, давайте разберёмся что не так.

El Vinto, 2023

Программирование 1С. Урок 9

Продолжим изучение 1С. Делаем мы это на живом примере, разрабатывая нашу собственную конфигурацию домашнего бюджета. Если вы по честному делаете мои домашние задания, то у вас уже должен быть создан справочники единиц измерения и продуктов питания, и одно привязано к другому, а также документы учета продуктов питания. Кстати, вы наверно обратили внимание, что учет количества продуктов питания идет с точностью до 3 знака, а размер числового параметра 15 (ведь некоторые продукты весовые с точностью до грамма).

Если вы уже успели заметить, у нас есть документ реализации для бытовой техники, но нет аналогичных документов для мелочевки и конечно же не будет для продуктов питания. Как думаете, почему?..Правильно, эти товары мы не будем продавать, а финансово говоря – будем их списывать по мере потребления. По этому будут документы похожие, но не совсем.

Теперь давайте сделаем аналогичный товарам отчет и по продуктам питания, чтобы знать сколько у нас их на остатках:

Хотелось бы в этом отчете увидеть ещё и единицу измерения, которую мы указывали для каждого товара. Конечно картофель вряд ли кто будет измерять поштучно, а мясо кусками, но всё же очень важно здесь отразить чтобы потом ничего не напутать, особенно если мы в будущем будем учитывать молоко и станет вдруг не ясно, считаем мы бутылками или литрами. Так вот, сделать это можно как минимум двумя способами (может есть и ещё, но навскидку не вспомню)) ).

Способ 1.

Раскрыть номенклатуру прямо в полях и вытянуть направо:

Способ 2.

Объявить получение нового поля в запросе:

А после этого это поле появится в настройках:

Обратите внимание, что по прежнему ничего не мешает сделать и первым способом, т.к. это поле есть и там и там; это два разных указателя на одно и тоже поле:

Что называется, выбирайте тот, который больше импонирует. Сделаем первым способом и увидим:

Вот только выглядит это не совсем впечатляюще. Обычно принято такие важные параметры выделять отдельной колонкой, но 1С увидела, что единица находится в подчинении номенклатуры и встроила в одну колонку с продуктом питания, автоматически отделив запятой.

А если по второму способу:

Тут у нас уже отдельное поле и 1С автоматически не стала встраивать его к номенклатуре, т.к. оно независимо полученное из запроса. Однако, и при первом способе можно получить такой же результат, если принудительно указать, что поля должны быть в отдельных колонка, для чего их нужно сгруппировать специальным способом:

Перенести поля туда методом Drag&Drop:

и указать тип группы как “В отдельной колонке”:

Получаем аналогичный результат:

Нужно привыкать к тому, что в программировании многие задачи можно решить множеством способов, и часто изначально не всегда представляется возможным понять какой из них будет наиболее рациональным. Также и сама платформа 1С позволяет решать задачи несколькими способами, как это было только что представлено; выбор лежит на программисте, какой способ для конкретной задачи он находит более оптимальным.

Теперь, когда мы обладаем кучей информации о том что у нас есть дома, пардон, на складе, и продукты питания, и мелочевка, и бытовая техника, есть информация о том кто что когда покупал, но всё-таки как-то не ясно кто в доме больше всего транжирит деньги. Кончено, подозрение есть, что это маманька со своей косметикой и новыми платьями, но это надо всё-таки проверить чтобы не быть голословным))). Вот только как нам собрать теперь все эти данные, а собрать их не так сложно. Давайте сделаем новый отчет, в котором будет представлена сводная информация, запрос у него будет таким:

Тут как-то получилось не очень и всё в куче. Давайте вначале поймем, что точная дата нам не особо нужна для анализа, а вот месяц, в котором эти затраты были, очень важен, т.к. все мы ориентируемся на зарплаты, а кто-то на пенсии и дотации. Давайте отчет представим разделенным по периодам. Делается это так, сначала добавим новую группировку:

И укажем вот такое поле:

В этой группировке создам ещё для месяца и для домочадца, перетащим в нижнюю иерархию детальные записи и в результате получаем вот так:

Посмотрим что получилось, а получилось весьма даже не плохо, кроме дат – вместо года и месяца в иерархи полная дата:

Такое представление ещё хуже, чем было. Давайте сделаем красиво, по этому поставьте курсор в иерархии групп на группировку года, выберите настройку группировки, а не отчета, теперь кликнем во вкладке “Условное оформление” по зеленому плюсу и добавим новую строку:

Т.е. текст формата:

ДФ=yyyy

Тоже самое сделайте и для группировки месяца, но формат будет другой (латинские буквы М):

ДФ=MMMM

Как понимаете, “y” (буква игрек, уай) – это от слова year (год), а “M” – это month (месяц). После этого получается так:

Ну, и теперь осталось отчет, что называется, полирнуть. Ну, в смысле отполировать.

Укажите расчет ресурсов следующим способом:

И казалось бы от такой манипуляции что радикально должно нового появиться, а получается так:

Т.е. программа посчитала все промежуточные итоги в каждой группировке, а ведь это нам и нужно было. Оказывается в моём отчете больше всех порастратил брат в сентябре, накупив холодильников))).

Идем далее. Поступление разных товаров в дом – это хорошо, но это полноценно всё-таки не отражает затраты. Дело в том, что поступление может быть и разным, например, взяли телевизор в кредит, но мы не потратились при этом ни на копейку. С другой стороны, мы могли дать друзьям шуруповёрт на недельку, он вышел с нашего остатка, но при этом денег мы за него не получили. По этому по всем правилам любое приобретение состоит из двух частей – передача товара или услуг и оплата. Но для того чтобы что-то платить нужны деньги, а в финансовом смысле – источники средств. Для фирмы – это выручка, инвестиции и уставной капитал, а для нашей конфигурации – это заработная плата, стипендия, пенсия и кредиты. Пора учитывать этот раздел. Сделаем документ “ПоступлениеДенежныхСредств”, который получается крайне простой:

Однако, тут нет важной для учета информации, какой источник доходов, чтобы потом определить, это у бати такая зарплата маленькая или у бабуси крутая пенсия)). Можно конечно сюда тоже добавить справочник, но вариантов не так много, и новые вряд ли появятся. По этому такие объекты чаще делают не на основе справочника, а на основе фиксированного списка (чтобы пользователь не мог создать ничего лишнего, а мог использовать только то, что предусмотрено конфигурацией). Есть для этого специальный объект – перечисление, но заполняется он данными не в рабочей среде, а непосредственно в конфигураторе. Давайте создадим такой в соответствующем разделе:

И добавим в него несколько значений:

Вот этипх:

Значение “Прочее” нужно чтобы пользователь мог туда включать всё остальное, что не входит в эти категории источников дохода, но тем не менее происходит, например, выиграл в лотерею, нашёл на улице, подарили на День рождения и т.д.

И добавим теперь реквизит с этим типом в наш новый документ:

В результате получится так:

Задание по уроку:

1. Добавьте во все товарные справочники единицы измерения, добавьте в сводный отчет количества прихода и единицы измерения.

2. Создайте новое перечисление “ТипПоступленияТоваров” со значениями “Покупка”, “Аренда” и сделайте реквизит в документе ПоступленияТоваровУслуг.

3. Создайте регистр накопления для учета денежных средств и сделайте соответствующую обработку проведения для документа поступления денежных средств так, как вы понимаете это.

Если всё получилось как нужно – молодцы! Если нет, давайте разберёмся что не так.

El Vinto, 2023

Программирование 1С. Урок 10

Типичная ситуация в работе программиста 1С – приходит вдруг с утра к вам в кабинет финансовый директор компании и заявляет. Товарищ программист, что-то какая-то бодяга у нас в управленческом учете. На кой ляд нам такое количество разных видов приходных документов? И на мелочевку, и на бытовую технику, и продукты питания. Наши экономисты уже забодались бегать от одного документа к другому. Хочу чтобы это всё учитывалось одним документом…и уходит…а вы после этого ещё минут пять сидите вот так:

…но это если вы только начинаете программировать на 1С, а вот если есть небольшой опыт, то сразу же поймете, что задача хотя и нетривиальная, но всё же не такая сложная. Давайте убедимся в этом наглядно. Добавить нужные табличные части в документ поступления товаров услуг – это не проблема, и мы это делать уже умеем. А вот что делать с данными? Как их после этого перебросить в этот документ, ну не вводить же их заново!

Для начала всё-таки модернизируем наш документ ПоступлениеТоваровУслуг, создав там табличные части по тому виду, которые они были в этих документах, но их придётся переименовать, т.к. нельзя в одном объекте делать табличные части или реквизиты с одинаковым названием:

На форму тоже добавим все эти табличные части.

Теперь саму форму нужно немного доработать – помните мы считали сумму по строке при помощи процедуры общего модуля? Она ведь сейчас будет считать только для табличной части “Товары”, т.к. мы это в ней явно указали, а для остальных табличных частей будет выдавать ошибку выполнения, т.к. программа будет пытаться обратиться к текущей строке таблицы Товары, в то время как текущая строка будет находится вообще в другой табличной части. Давайте доработаем код процедуры и сделаем его таким:

Видите, я могу обратиться к табличной части не только “через точку”, но и через именованный массив – программа будет брать имя табличной части из переменной ИмяТабличнойЧасти, которое мы будем передавать при вызове этой процедуры:

Кстати, а вы не заметили, что что-то тут лишнее? Две процедуры выполняют одно и то же. Давайте мы оставим только одну процедуру и дадим ей немного общее наименование, а вторая вообще больше не нужна:

Но на эти процедуры ссылались события в двух колонках – “Количество” и “Цена”, по этому там тоже надо теперь указать эту новую процедуру:

Тоже самое сделать и для колонки количества, указав ту же самую процедуру:

Добавим теперь на каждую табличную часть новую вкладку со своей табличной частью, а то сейчас у нас только товары и услуги. Делается это при помощи добавления новой страницы (это сама вкладка):

, указав элемент “Страница”:

, а затем и самой табличной части перетаскиванием справа налево:

Теперь дадим самой вкладке вразумительное имя по аналогии предыдущими:

Теперь добавьте реквизит документа “ИдентификаторСтарогоДокумента”, значение которого станет понятно чуть позже:

Теперь познакомимся с новый объектом метаданных – Обработка, и сразу же добавим новую с именем “ПереносДанных”:

Сделайте ещё одну подсистему и включите туда эту обработку:

Теперь добавим форму:

Теперь на форму нужно добавить единственную кнопку, по нажатию которой будет происходить перенос данных из существующих документов в наш новый переделанный с множеством табличных частей. Добавьте новый элемент “Кнопка” на форму:

К слову говоря, подобным способом добавляются элементы на все формы, в т.ч. справочников и документов, но мы делали это немного другим способом, т.к. у нас был элемент отображения реквизита и мы просто перетягивали его справа налево.

Кнопка появилась, но теперь нужно добавить команду – реакцию по нажатию на кнопку. Для этого нужно открыть вкладку “Команды” и добавить новую:

Теперь в свойствах кликнуть по созданию обработчика:

В этот раз обработчик будет включать в себя две процедуры – на клиенте и на сервере, т.к. нам понадобятся процедуры и функции, которые характерны только для серверного исполнения. В результате платформа автоматически подготовит их для программирования:

Теперь нужно возвратиться обратно в графическое представление формы и привязать кнопку к команде и дать человеческие наименования:

Переходим снова в код. Делаем так:

Давайте разбираться что тут. Сначала я сделал запрос для того чтобы перебрать все уже созданные документы ПоступлениеМелочевки.

Получаю уникальный идентификатор каждого документа. Этот идентификатор – объект платформы, который легко можно преобразовать в строку. Строка получается 36 символов. Каждый объект данных 1С имеет уникальную идентификацию в пределах одной базы. Она нужна мне чтобы привязать создаваемые автоматически документы с исходным “старым” документом. Такая идентификация мне нужна чтобы однозначно определить перегружался ли этот документ уже или нет, на случай, если я захочу запустить обработку повторно. Повторный запуск может потребоваться, если при первом что-то пошло не так или мы уже успели внести ещё данных по мелочевки “старым” способом.

НайтиДокументПоИдентификатору() – это нестандартная функция, как может показаться, которая будет искать документ по признаку идентификатора; я разместил её в этом же модуле:

Эта функция при помощи простого запроса с условием ищет тот документ ПоступленияТоваровУслуг, где реквизит ИдентификаторСтарогоДокумента будет равен идентификатору исходного документа (мелочёвки, продуктов питания и т.п.). Если результат поиска отрицательный, то функция возвратит значение равное “Неопределено”.

После этого я проверяю удалось ли найти документ. Если не удалось, то будет создан новый и сразу же определен реквизит с идентификатором и дата (без указания даты документ не удастся записать).

Следующие действия – это перенести построчно табличную часть с товарами. Тут должно быть понятно – берём строку исходного документа – создаём строку конечного документа.

В результате получаем что-то вроде этого:

Тут хорошо видно, что два первых документа без идентификатора – это те, что создавали интерактивно (вручную), а два с идентификатором – это те, что переносили обработкой (именно тогда мы его устанавливали). Сам документ теперь выглядит так:

Задание по уроку:

1. Добавьте на форму документа ПоступлениеТоваровУслуг страницу с табличной части “ПродуктыПитания”, сделайте необходимый расчет суммы по строке.

2. Добавьте в обработку перенос документа ПродуктыПитания

3. Ранее я говорил, что перед проведением документа всегда автоматически происходит его запись, однако при этом принудительно делаю перед этим запись. Как думаете, почему я так сделал?

Если всё получилось как нужно – молодцы! Если нет, давайте разберёмся что не так.

El Vinto, 2023

Как для сайта выделить терабайты дисковой памяти и ничего за это не платить

Вот вы решили сделать свой сайт, выбрали уже доменное имя, купили хостинг и закинули движок на сервер хостера. К вам стали подтягиваться посетители, вы стали постить тексты, фото, видо и вот вдруг обнаруживается, что места больше нет. Вы заходите в панель управления, а там предлагается объём до 100 ГБ и стоить это будет “космос”. Так что, кина не будет? (цит. из ф. “Джентельмены удачи”). Ну, мы же айтишники, мы понимаем, что в ИТ можно всё!..ну, почти всё))…

Для начала нам потребуется перевести хостинг на VPS. И вы не поверите, но абонентская плата будет меньше за те же ресурсы. По крайней мере у меня на Бегете (на нём я около 5 лет) это было именно так. Кстати, вот партнерская ссылка, по которой и мне будет профит и вам скидка:

https://beget.com/p1223557

Для тех, кто не имел с этим дело скажу. Обычный хостинг – это фактически папка на сервере, где ещё таких как вы могут быть сотни. Один мощный сервер распределяет свои ресурсы между множеством сайтов таких же как и вы клиентов. Поддержка, обслуживание и работы на этом сервере требуют квалифицированный персонал, по этому за это берутся отдельные деньги. VPS – это вам даётся сервер с уже предустановленной операционной системой, в частности Ubuntu, и установленным на неё ПО для работы сайта. Чаще всего это пакет LAMP (Linux, Apache, MySQL, PHP). Сам сервере виртуальный, но для нас это не имеет никакого значения, т.к. ничто не будет отличать его от реального. Но и здесь хостер выделит вам всё равно те же 10 ГБ (начальный уровень), а за всё что больше придётся доплатить…это если вы что-то не знаете, что знаю я)))…Открываем папку моего сайта https://elvinto.ru и смотрим размер свободного месте на диске:

Внимательно смотрим в правый нижний угол – 94 ГБ и з 1.8 ТБ свободно. Теперь взглянем, что в моём тарифном плане в панели управления:

Получается как в сказке “Карлик нос” – избушка изнутри больше, чем снаружи. Так-то оно так, да не совсем. Пора открывать карты)).

Есть у меня на этом VPS-сервере портал в другое измерение, а именно – на мой домашний комп. Весь процесс сводится к монтировании домашней папки в папку VPS-сервера. Домашний сервер у меня тоже на Ubuntu, дома потребуется “белый” IP, по этому и для этого примера тоже буду писать исходя из этого. Пользователь на VPS vpsuser, на домашнем компе – homeuser. В папке homeuser есть папка content, которая и является тем терабайтным хранилищем, которое мы подключаем.

Настроим сначала сервер VPS.

Для этого сначала нужно установить sshfs:

sudo apt-get install sshfs

Теперь надо создать пару ключей, ведь мы же не будем вручную контролировать процесс подключения при каждой перезагрузке и вводить пароль к домашнему серверу.

ssh-keygen -b 4096

В результате получим в папке ~/.ssh пару файлов – публичный и приватный ключ. Теперь публичный ключ можно скопировать себе на домашний комп. Сделал я это просто – выложил на сайте по ссылке прямо в корне elvinto.ru/id_rsa.pub (сейчас там нет этого файла, чтобы не засорять корень), а с домашнего компа скачал из браузера. Бояться, что его кто-то украдёт не надо, т.к. красть его глупо, это публичный ключ и расшифровать закодированную им информацию может только обладатель приватного ключа, который остался в папке .ssh на VPS (вы же ничего не напутали?!!)) ).

Настройка домашнего сервера.

Создайте удобочитаемую папку на том диске, где у вас эти самые терабайты. У меня в примере это /home/homeuser/content. Теперь в папку /home/.ssh закиньте id_rsa.pub и переименуйте его в authorized_keys (если такой файл уже есть, то допишите в конец этого файла ваш id_rsa.pub). У файла authorized_keys обязательно должны быть права (с другими может отказать в авторизации по ключу и потребует ввести пользователь и пароль):

chmod 0600 authorized_keys

Снова продолжаем настраивать VPS.

Теперь нужно в файл /etc/rc.local (если его нет, см.далее) перед exit 0 добавить нужный текст (для сайта на WordPress – расширяется папка wp-content/uploads):

sshfs -o idmap=user,allow_other,reconnect,ServerAliveInterval=600,IdentityFile=/home/vpsuser/.ssh/id_rsa -p 22 homeuser@ВашБелыйIPадрес:/home/homeuser/content /ПутьКВашемуСайту/wp-content/uploads

Если файла rc.local нет, значит сервис rc-local просто не включен, такое встречается на Ubuntu >= 20.04. Всё делается просто. Создайте при помощи, например, nano или mcedit этот файл и дайте ему права на запуск. Файл должен начинаться со спец.строки и заканчиваться exit 0:

Теперь нужно включить сервис rc-local:

sudo systemctl enable rc-local

и стартануть его:

sudo systemctl start rc-local.service

Проверяем на VPS папку, куда монтировали, она должна ссылаться на ваш домашний сервер.

П.С.:

Вы должны понимать, что качество вашего сайта после этого будет обеспечиваться двумя основными факторами – стабильность и скорость домашнего инета и надежность домашнего хранилища. Но если речь идет о бесплатном обеспечении сайта терабайтами, то уж постарайтесь это осуществить…как-то))).

El Vinto, 2023