Предлагаю открыть рубрику Копилка Опыта.
Можно описывать трудные ситуации при программировании и делится опытом по их преодолению
Первый пост сподвигло написать большое количество нареканий типа "Я в 1С ну бум-бум, видите ли перешел из СИ - очень трудно въехать...". Заканчивается, зачастую просьбой о помощи в элементарном вопроссе, хорошо кстати освещенном в литературе к 1С.
Итак, как мне помог СИ очень быстро сориентироватся в ситуации:
Как думаете, что будет в тзТаб1? Правильный ответ: полная копия (даже не копия!?) тзТаб2 после свёртки. Вот теперь оперируя терминами Си: тзТаб1 и тзТаб2 - переменные содержащие ССЫЛКИ на конкретные данные, следовательно
тзТаб2 = тзТаб1;
мы переменной присваиваем ссылку из другой переменной и обе они ссылаются на одни и те же данные. Вывод: в случае сложных данных (массив, структура) в 1С при присваивании присваиваются не сами данные, а только ссылки на них.
Приветствую!
Я может быть скорее не прав, чем прав, а может быть уже мертв, чем жив, но...
После сортировки и свертки таблицы, по моему разумению, должны содержать несколько иные данные... Скажем, Поставщик сгруппировался, какие-то данные суммировались (в случае, когда суммируемые колонки были заданы ;-) ) => количество строк уже уменьшилось... а после сортировки количество строк ни в коем случае не уменьшается, а просто меняется их индекс (типа встроенный атрибут НомерСтроки()) а как же потом сравнить их... по значению разве что... а смысл тогда во всей этой охоте?
имхо: создаем нужное количество ТЗ, выгружаем то, что надо, группируем так, как надо, потом свертываем, если надо, затем или выводим или получаем нужные итоги по колонкам. Вот.
Вопрос у меня такой: опять же по ТЗ:
Почему вот это не работает?:
ТЗУсл=СоздатьОбъект("ТаблицаЗначений");
ТЗМат=СоздатьОбъект("ТаблицаЗначений");
ВыгрузитьТабличнуюЧасть(ТЗУсл,);
ВыгрузитьТабличнуюЧасть(ТЗМат,);
//ТЗУсл.ВыбратьСтроки();
//Пока ТЗУсл.ПолучитьСтроку()=1 Цикл
// Если ТЗУсл.Товар.ВидТовара = Перечисление.ВидыТоваров.Товар Тогда
// ТЗУсл.УдалитьСтроку();
// ТЗУсл.ВыбратьСтроки();
// Пока ТЗУсл.ПолучитьСтроку()=1 Цикл
// Если ТЗУсл.Товар.ВидТовара = Перечисление.ВидыТоваров.Товар Тогда
// ТЗУсл.УдалитьСтроку();
// ТЗУсл.ТекущаяСтрока(ТЗУсл.ТекущаяСтрока()-1);
// КонецЕсли;
// КонецЦикла;
// КонецЕсли;
//КонецЦикла;
//ТЗМат.ВыбратьСтроки();
//Пока ТЗМат.ПолучитьСтроку()=1 Цикл
// Если ТЗМат.Товар.ВидТовара = Перечисление.ВидыТоваров.Услуга Тогда
// ТЗМат.УдалитьСтроку();
// ТЗМат.ВыбратьСтроки();
// Пока ТЗМат.ПолучитьСтроку()=1 Цикл
// Если ТЗМат.Товар.ВидТовара = Перечисление.ВидыТоваров.Услуга Тогда
// ТЗМат.УдалитьСтроку();
// ТЗМат.ТекущаяСтрока(ТЗМат.ТекущаяСтрока()-1);
// КонецЕсли;
// КонецЦикла;
// КонецЕсли;
//КонецЦикла;
Эксперименты типа ТекущаяСтрока-1 были добавлены уже потом, когда стало понятно, что что-то здесь не чисто... Думал как в Экселе, после удаления текущей строкой автоматом становится следующая...
Циклы менял: вместо выбрать-получить - для-по все одно и тож.
Баг в чем: Если в ТЗДок 4 строки (2 услуги, 2 материалы), тогда в этих ТЗ - 3 строки, в одной (1) 2 усл, 1 мат, а в другой тож 3 стр. 2 мат, 1 усл. %-(
Получается, что после удаления к-л строки цикл прерывается... А почему?
Вразумите, плз, на какие вилы опять встал отрок неприкаянный...
Не понятно, зачем ты создаешь двойной цикл? ИМХО достаточно написать следующее
Код
ТЗУсл.ВыбратьСтроки();
Пока ТЗУсл.ПолучитьСтроку()=1 Цикл
Если ТЗУсл.Товар.ВидТовара = Перечисление.ВидыТоваров.Товар Тогда
ТЗУсл.УдалитьСтроку();
ТЗУсл.ВыбратьСтроки();
КонецЕсли;
КонецЦикла;
Вы чо-то не ту про ТЗ батву ведете. На мой взгляд, крайне не корректно удалять что-то из объекта, по которому открыта выборка. Я бы использовал (и использую) такую конструкцию:
Код
К=1;
Пока К<=ТЗ.КоличествоСтрок() Цикл
ТЗ.ПолучитьСтрокуПоНомеру(К);
...
Если Условие Тогда
ТЗ.УдалитьСтроку(К);
Иначе
К=К+1;
КонецЕсли;
КонецЦикла;
ребята, вы че? прикалываетесь?
кс=тз.количествострок()
для сч=-кс по -1 цикл
тз.получитьстркупономеру(-сч)
если условие на рекв тогда
тз.удалитьстроку()
По поводу ТЗ.УдалитьСтроку() и ТЗ.ВыбратьСтроки() или двойного цикла: я давно пришел к выводу, что самый эффеквный способ удалить строки из ТЗ по условию - это просто перегрузиться в другую ТЗ по заданным условиям. Вот достаточно быстро работающая функция перегруза:
Функция глПерегрузитьТЗ(пТЗ,пУсловие,пЗначение,пНомКол) экспорт
// пУсловие "=" или ">" или "<" или "<>" или "in,=К"
// nНомКол - номер колонки в которой nЗначение должно удовлетворять условию
// "=К" - сравнение значений в двух колонках, в этом случае nЗначение номер второй колоки
//--- возвращает ТЗ отфильтрованную по условиию в заданной колонке
//-- пример вызова: ТЗ.Загрузить(глПерегрузитьТЗ(ТЗ,"in",5,1));
Nil=ПолучитьПустоеЗначение();
Контроль="=,<,>,<>,in,=К";
Контроль=СтрЗаменить(Контроль,",",РазделительСтрок);
Ошибка=1;
Для А=1 По СтрКоличествоСтрок(Контроль) Цикл
ТС=СокрЛП(СтрПолучитьСтроку(Контроль,А));
Если ТС=пУсловие Тогда
Ошибка=0;
Прервать;
КонецЕсли;
КонецЦикла;
Если Ошибка=1 Тогда
Сообщить("неверное условие "+пУсловие,"!");
Возврат Nil;
КонецЕсли;
вТЗ=СоздатьОбъект("ТаблицаЗначений");
пУсловие=СокрЛП(пУсловие);
вТЗ.Загрузить(пТЗ);
вТЗ.УдалитьСтроки();
Для А=1 По пТЗ.КоличествоСтрок() Цикл
Если пУсловие="=К" Тогда
Если пТЗ.ПолучитьЗначение(А,пНомКол)=пТЗ.ПолучитьЗначение(А,пЗначение) Тогда
вТЗ.НоваяСтрока();
Для Кол=1 по вТЗ.КоличествоКолонок() Цикл
вТЗ.УстановитьЗначение(вТЗ.КоличествоСтрок(),Кол,пТЗ.ПолучитьЗначение(А,Кол));
КонецЦикла;
КонецЕсли;
ИначеЕсли пУсловие="=" Тогда
Если пТЗ.ПолучитьЗначение(А,пНомКол)=пЗначение Тогда
вТЗ.НоваяСтрока();
Для Кол=1 по вТЗ.КоличествоКолонок() Цикл
вТЗ.УстановитьЗначение(вТЗ.КоличествоСтрок(),Кол,пТЗ.ПолучитьЗначение(А,Кол));
КонецЦикла;
КонецЕсли;
ИначеЕсли пУсловие=">" Тогда
Если пТЗ.ПолучитьЗначение(А,пНомКол)>пЗначение Тогда
вТЗ.НоваяСтрока();
Для Кол=1 по вТЗ.КоличествоКолонок() Цикл
вТЗ.УстановитьЗначение(вТЗ.КоличествоСтрок(),Кол,пТЗ.ПолучитьЗначение(А,Кол));
КонецЦикла;
КонецЕсли;
ИначеЕсли пУсловие="<" Тогда
Если пТЗ.ПолучитьЗначение(А,пНомКол)<пЗначение Тогда
вТЗ.НоваяСтрока();
Для Кол=1 по вТЗ.КоличествоКолонок() Цикл
вТЗ.УстановитьЗначение(вТЗ.КоличествоСтрок(),Кол,пТЗ.ПолучитьЗначение(А,Кол));
КонецЦикла;
КонецЕсли;
ИначеЕсли пУсловие="<>" Тогда
Если пТЗ.ПолучитьЗначение(А,пНомКол)<>пЗначение Тогда
вТЗ.НоваяСтрока();
Для Кол=1 по вТЗ.КоличествоКолонок() Цикл
вТЗ.УстановитьЗначение(вТЗ.КоличествоСтрок(),Кол,пТЗ.ПолучитьЗначение(А,Кол));
КонецЦикла;
КонецЕсли;
ИначеЕсли пУсловие="in" Тогда
ТекСтр=Строка(пТЗ.ПолучитьЗначение(А,пНомКол));
Если Найти(ТекСтр,пЗначение)>0 Тогда
вТЗ.НоваяСтрока();
Для Кол=1 по вТЗ.КоличествоКолонок() Цикл
вТЗ.УстановитьЗначение(вТЗ.КоличествоСтрок(),Кол,пТЗ.ПолучитьЗначение(А,Кол));
КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Возврат вТЗ;
КонецФункции
К обработке http://infostart.ru/projects/397/?ref=440 AlexQC подкинул весьма интересную идею использования имени принтера в параметрах страницы. Привожу пример реализации (печатается до 6-ти отборочных/перемещений пакетом на три принтера):
1 А в это время где-то в Глобальном Модуле (переменны естественно Экспорт):
// Ладно, приведу и сами переменные
Перем PrinterDefault Экспорт;
Перем ПринтерОтдела3 Экспорт;
Перем ПринтерЭкспедиции Экспорт;
2. В Обработке печати
Если БыстраяПечать = 0 Тогда
Если Строка(Конт.Склад) = "3 Реактивы и штуч.отдел" Тогда
Таб2.ПараметрыСтраницы(2,,1,5,5,5,5,5,5,1,1, ПринтерОтдела3);
Таб2.Показать("Аптека");
ИначеЕсли Строка(Конт.Склад) = "9 Експедиція-Товар" Тогда
Таб2.ПараметрыСтраницы(2,,1,5,5,5,5,5,5,1,1, ПринтерЭкспедиции);
Таб2.Показать("Аптека");
Иначе
Таб2.ПараметрыСтраницы(2,,1,5,5,5,5,5,5,1,1, PrinterDefault);
Таб2.Показать("Аптека");
КонецЕсли;
Иначе
Если Строка(Конт.Склад) = "3 Реактивы и штуч.отдел" Тогда
Таб2.ПараметрыСтраницы(2,,1,5,5,5,5,5,5,1,1, ПринтерОтдела3);
Таб2.Напечатать(1);
ИначеЕсли Строка(Конт.Склад) = "9 Експедиція-Товар" Тогда
Таб2.ПараметрыСтраницы(2,,1,5,5,5,5,5,5,1,1, ПринтерЭкспедиции);
Таб2.Напечатать(1);
Иначе
Таб2.ПараметрыСтраницы(2,,1,5,5,5,5,5,5,1,1, PrinterDefault);
Таб2.Напечатать(1);
КонецЕсли;
КонецЕсли;
Хочу поделится одной ерундовиной - может кому-то пригодится.
Вчера, когда упал сервер домена, одна Хомка решила, что она самая умная и перетащила на себя права сервера (с каких хыров неясно) и сегодня 9 компов ни в какую не видят серверов. Хотя друг друга видят опять же через сервер. Повозился конечно пока вычислил эту долбанутую хомку. И чтоб не повадно было в следующий раз написал вот эту приблуду (с раширением reg) и натравил на шизанутую хомку (назвал XP_NoServer) - вылечилось. Никогда б не подумал, что эта ущербная и урезанная хомка может претендовать на роль сервера.
Тоже поделюсь кое-чем, прошу не пиннать, ведь я не системщик. Был клиент, у которого стояла база на затрапезном компе. Однажды они вызывают и говорят, что все слетело вдруг неожиданно. Проверяю: 1С вылетает по какой-то системной ошибке. Не знаю как, но интуитивно я допер тогда, что надо войти в каталог ИБ м стереть папку SYSLOG со всем содержимым. Все заработало. Этот метод помогал мне после раз десять.
_______________
Мож спецы путно объяснят, что там, ведь интуиция - это не всегда надежно ))
Поделюсь одной фиговиной, сам обнаружил совершенно случайно:
Иногда в силу влияний пятен на солнце или пролетающих мимо солнечной системы комет, при аварийном завершении работы пользователей 1С 7.7 возникают какие-то глюки с файлом хранения настроек (того самого, который лежит в каталоге пользователя и имеет расширение .cfg). Этот файл становится сравнительно тяжёлым (уж и не помню точно сколько, но раза в два тяжелее обычных). В результате при формировании любых отчётных форм вывод результата на экран тормозит просто ужасно! Причм заметно, что, предположим, запрос к бух. итогам проходит достаточно быстро, а вот метод Показать() подвешивает машину на долгое время. Видимо 1С-ина пытается прочитать из файла настроек координаты окна и зацикливается. Через какое-то время отчёт выводится. поэтому пользователь может и не обращаться к администратору, списывая тормоза на производительность компьютера/сети/антивируса и т.п.
Помогает только удаление этого файла (а до кучи и полная чистка каталога пользователя). Короче, будте бдительны!
А вот для любителей двуязычного интрефейса:
как думаете, что получится, если в модуле написать 2 процедуры
ПриОткрытии() и OnOpen()?
А получается забавная вещь:
1. Синтаксис контроль посчитает из разными (!) и ни на что не ругнется
2. Если в системе язык по умолчанию русский, отработает процедура ПриОткрытии() и полностью будет проигнорирована OnOpen()
3. Для английского - все наоборот.
Простой практический совет.
Прежде чем обговаривать сумму по работе по типовой бухии - как минимум запустите технологический анализ БУ. Посмотрите. Подумайте. Скорректируйте свою ценовую политику. ;-)
для целей отладки иногда по коду расставляют ТЗ.ВыбратьСтроку(,).
Перед этим напишите ТЗ.ВидимостьКолонки("НомерСтроки",1) - будет легче ориентироваться...
Вы решили рассчитать остатки товаров и используете для этого таблицу значений? Что ж, на каком-то этапе вам, вероятно, потребуется сортировка по номенклатуре. Я несколько раз наталкивался на такой глюк ( :( после получасового колупания процедуры проведения документа в отладчике): сортировка по элементу справочника не всегда отрабатывает корректно. Например, если у вас в таблице несколько товаров с одинаковым наименованием, то эти товары, бывают, выстраиваются не друг за другом, а вперемешку. Поэтому, совет: добавьте в таблицу еще одну колонку, занесите туда код номенклатуры из строк и сортируйте по коду. Работает всегда корректно.
2O-Planet:
при расчете остатков у тебя выстраиваются не элементы справочника, а субконто, являющиеся элементами этого справочника. А это немного не одно и то же
O-Planet Написал:
-------------------------------------------------------
> вылетает по какой-то системной ошибке. Не знаю как, но интуитивно я допер тогда, что надо войти в
> каталог ИБ м стереть папку SYSLOG со всем содержимым. Все заработало. Этот метод помогал мне
> после раз десять.
> _______________
> Мож спецы путно объяснят, что там, ведь интуиция - это не всегда надежно ))
Проблема не во всей папке SYSLOG, но только с файлом журнала регистрации 1cv7.mlg.
Кроме удаления этого файла помогают другие методы:
1. Открыть файл в блокноте, записать, закрыть.
2. Выполнить проверку диска с исправлением ошибок.
А также :
3. (к п1)Открыть а AkelPad (идет с тоталкоммандером - большой файл блокнот не укусит) и удалить дефектные строки - они отличаются от нормальных суммашедшей длиной и крякозябликами в содержании, а затем сохранить.
4. Почаще архивировать лог.
VasilyKushnir Написал:
-------------------------------------------------------
> А также :
> 3. (к п1)Открыть а AkelPad (идет с тоталкоммандером - большой файл блокнот не укусит)
В win95, 98, ME было ограничение на размер файла для блоктнота, но ИМХО в Win NT4, 2000, XP, 2003 такого ограничениея нет.
Если блокнот не кусает и нет AkelPad'а, можно воспользоваться WordPad'ом.
> и удалить дефектные строки - они отличаются от
> нормальных суммашедшей длиной и крякозябликами в
> содержании, а затем сохранить.
Дефектные строки удалять не пробовала. Чаще причина ошибки не дефектне строки, но состояние самого файла. На каком-то уровне он помечен, что заблокирован (или открыт). Перезагрузка окон не помогает. Текстовые редакторы при записи (проверка диска при исправлении) снимают пометку или закрывают файл. Все это ИМХО.
Это не означает, что дефектные строки нельзя удалять. Без них система хуже работать точно не будет.
По поводу пометки на заблокированность. Чаще всего она появляется, когда сеть нестабильно работает, и если в этой сети еще где-то слабый комп стоит. И - вопрос по ходу. У клиента стоит терминал под 2003. Такая вот ботва: почему-то слетает иногда список баз в меню запускам 1С. Мож кто что подскажет?
Информация о списке баз храниться в реестре в ветке HKEY_CURRENT_USER. Вероятно, в результате какого-то сбоя, эта ветка подменяется на HKEY_USERS\.DEFAULT
В mlg тупая 1С иногда подставляет код eof (конец файла). Причем, не обязательно в конце. В этом давно убедился, когда писал фильтрацию лога для MPlus.
Примечание: никто уже давно этот символ не пишет в конце файла
2O-Planet: не мог раньше про список баз сказать! ;) Только что компоненту выложил, а можно было приделать сохранение и восстановление
ключика \Software\1C\1CV7\7.7\Titles в ветке HKEY_CURRENT_USER
Вы хотите перебрать строки этой табличной части, учитывая все, кроме какой-то одной. Самое интересное, что стандартная констукция ВыбратьСтроки() - ПолучитьСтроку() здесь не подойдет, потому что реквизит НомерСтроки показывает всегда одно и то же значение: номер выбранной интеравтивно в форме документа строки. Поступаем просто:
Код
Для К=1 По КоличествоСтрок() Цикл
ПолучитьСтрокуПоНомеру(К);
Если К=НужныйНомер Тогда
...
Иначе
...
КонецЕсли;
КонецЦикла;
Показать полностью
Делаю небольшое уточнение в силу полученных комментариев: речь идет о случае, когда Вы хотите перебрать строки в форме открытого документа, не используя функцию "СоздатьОбъект"
Открываем накладную, выбираем в ней контрагента, печатаем, слышим жуткий вопль, что в "ЧП ХРУЛЕВ" пропущены почему-то Р и Л! Разумеется, накладную мы не закроем, а откроем справочник контрагентов, внесем нужные исправления и вновь отправим на печать. Что ж, вопль раздастся вновь. Оказывается, любые изменения, которые бы вы не внесли в элемент справочника, выбранный в документе, не вступят в силу, пока документ открыт, или пока вы не перевыберите этот элемент в форме документа явно. Странно. Казалось бы, 1С должна находить новое наименование просто по ссылке. Но нет. Такое чувство, что где-то при открытой форме документа хранятся все копии элементов справочников по ссылкам ...
Эту фичу следует учитывать, когда предполагается параллельная работа в нескольких формах.
Впрочем, описанная ситуация полностью пропадает, когда вы не ссылку
Код
Сообщить(Контрагент.Наименование);
Показать полностью
, а делаете предварительное позиционирование в справочнике по ссылке:
O-Planet Написал:
-------------------------------------------------------
> Самое интересное, что стандартная констукция
> ВыбратьСтроки() - ПолучитьСтроку() здесь не
> подойдет, потому что реквизит НомерСтроки
> показывает всегда одно и то же значение: номер
> выбранной интеравтивно в форме документа строки.
Странно, в типовых конфигурациях активно используется атрибут НомерСтроки. В т.ч. внутри конструкции ВыбратьСтроки() - ПолучитьСтроку() в модуле формы документа. Там, почему-то, таких проблем не наблюдается.
Есть похожая засада при работе с таблицей значений. У нее есть атрибут - НомерСтроки и метод ТекущаяСтрока(). НомерСтроки относится к выборке строк, но ТекущаяСтрока() - к экранной форме.
O-Planet Написал:
-------------------------------------------------------
> Глюк при печати, и не только...
>
> Впрочем, описанная ситуация полностью пропадает,
> когда вы не ссылку
>
Сообщить(Контрагент.Наименование);
> , а делаете предварительное позиционирование в
> справочнике по ссылке:
>
Спр=СоздатьОбъект("Справочник.Контрагенты")
> Спр.НайтиЭлемент(Контрагент);
> Сообщить(Спр.Наименование);
>
Можно попробовать так:
Если форму элемента справочника открывать через кнопку "О", которая, как правило, находится справа от редактируемого реквизита, то таких проблем не возникает. Однако, в этом случае, документ помечается как измененный, хотя никаких изменений самого документа не происходило.
Надо быть осторожными с описанной O-Planet'ом фичей. Многие начинающие пользователи накалываются на этом.
Ха! Вот что у меня получилось в результате экспериментов.
Документ Счет, стандартная бухгалтерия.
В печатной форме стояло:
Плательщик: [Контрагент.ПолнНаименование]
При изменении в справочнике полного наименования без переввода Контрагента в документе при печати ничего не меняется.
ОДНАКО, если написать в печатной форме:
Плательщик: [Контрагент.ТекущийЭлемент().ПолнНаименование]
все прекрасно выводится на печать в измененном виде
Отсюда вывод:
1. При вводе элемента справочника все его реквизиты 1С, похоже, сразу помещает в память и при выводе реквизитов обращается уже не по ссылке на элемент, а просто берет их из памяти.
2. Добавление ТекущийЭлемент() заставляет 1С еще раз обратиться к элементу и загрузить в память уже измененные реквизиты.
3. Если сильно хочется отлавливать изменения "на лету" надо везде, где идет обращение к реквизитам, вставлять ТекущийЭлемент():
ИНН=Контрагент.ТекущийЭлемент().ИНН
Адрес=Контрагент.ТекущийЭлемент().Адрес
и т.д. и т.п.
> Если форму элемента справочника открывать через
> кнопку "О", которая, как правило, находится справа
> от редактируемого реквизита, то таких проблем не
> возникает. Однако, в этом случае, документ
> помечается как измененный, хотя никаких изменений
> самого документа не происходило.
Кнопка "О" тут вообще не при теме: O-Planet имел в виду изменения в справочнике открытием справочника "на стороне", а не через документ.
Через документ и без кнопочки "О" (простым открытием в поле ввода) все изменения прекрасно проходят, т.к. происходит пере-ввод элемента (см. выше).
По поводу перебора строк. Я забыл сделать ударение на то, что фиксированное значение НомерСтроки появляется ни тогда, когда я использовал функцию "СоздатьОбъект" и нахожу нужный документ, а тогда, когда пытаюсь перебрать строки в форме открытого документа.
> При вводе элемента справочника все его реквизиты 1С, похоже, сразу помещает в память
Очень это смахивает на маразм программера, писавшего 1С. как-то круто очень звучит! Заметьте, что это же относится и к табличной части. А если у меня 1000 строк с номенклатурой? 1С всю инфу по ним хранит в памяти, когда документ открыт? В swap-файле? А потом все спрашивают, и почему оно глючит...
> Добавление ТекущийЭлемент() заставляет 1С еще раз обратиться к элементу и загрузить в память уже измененные реквизиты.
А вот интересно, если после этого вновь использовать Контрагент.Наименование, то оно напечатается старым, или первое же обращение Контрагент.ТекущийЭлемент() переписывает где-то всю инфу? Если второе, то лучше не злоупотреблять текущим элементом...
А со строками в ТЧ документа все ясно:
НомерСтроки
Синтаксис:
НомерСтроки
Назначение:
Доступ к номеру строки многострочной части документа.
Замечание:
Атрибут имеет смысл только при выбранной строке. Подробнее см. в документации, глава 'Работа с Документами'
Abadonna Написал:
-------------------------------------------------------
> Отсюда вывод:
> 1. При вводе элемента справочника все его
> реквизиты 1С, похоже, сразу помещает в память и
> при выводе реквизитов обращается уже не по ссылке
> на элемент, а просто берет их из памяти.
> 2. Добавление ТекущийЭлемент() заставляет 1С еще
> раз обратиться к элементу и загрузить в память уже
> измененные реквизиты.
> 3. Если сильно хочется отлавливать изменения "на
> лету" надо везде, где идет обращение к
> реквизитам, вставлять ТекущийЭлемент():
> ИНН=Контрагент.ТекущийЭлемент().ИНН
> Адрес=Контрагент.ТекущийЭлемент().Адрес
> и т.д. и т.п.
О, кстати, теперь стало понятно, чем отличается Контрагент.ТекущийЭлемент().Адрес от Контрагент.Адрес.
Я когда так, когда сяк писал, т.к. по обоим способам работало. Теперь понятно в каких случаях лучше применять .ТекущийЭлемент().
>Вдруг оно всякий раз память переписывает!
Скорее всего и переписывает, но в то же адресное пространство наверняка. Да и вообще, изменять элемент лучше всего через документ, а не "на строне", тогда и голову забивать не надо как оно и что...
O-Planet Написал:
-------------------------------------------------------
> > При вводе элемента справочника все его реквизиты 1С, похоже, сразу помещает в память
> Очень это смахивает на маразм программера, писавшего 1С. как-то круто очень звучит! Заметьте,
> что это же относится и к табличной части.
Вероятно, Сергей Нуралиев решал вопросы быстродействия.
По моим подсчетам конструкция Контрагент.ТекущийЭлемент().ПолнНаименование работает от 6 до 20 раз медленее, чем Контрагент.ПолнНаименование.
Из теории программирования известно, что время выполнения кода и требования к объему памяти находятся в обратной зависимости.
> А вот интересно, если после этого вновь использовать Контрагент.Наименование, то оно
> напечатается старым, или первое же обращение Контрагент.ТекущийЭлемент() переписывает где-то
> всю инфу? Если второе, то лучше не злоупотреблять текущим элементом...
ИМХО первое.
Что-бы из документа печатались новые данные необходимо выполнить код:
Извини, не понял логики
> > А вот интересно, если после этого вновь
> использовать Контрагент.Наименование, то оно
> > напечатается старым, или первое же обращение
> Контрагент.ТекущийЭлемент() переписывает где-то
> > всю инфу?
Отвечаешь: > ИМХО первое.
И тут же: > Что-бы из документа печатались новые данные
> необходимо выполнить код:
> Контрагент = Контрагент.ТекущийЭлемент();
Из твоего же ответа следует, что не первое, а второе
Должен признать, что poppy права!
Проверил специально:
Контрагент.ТекущийЭлемент().ПолнНаименование изменяет ТОЛЬКО полное наименование при печати, не влияя на Наименование (ктр. я тоже поменял).
Так что опасения O-Panet, что перепеписывает ВСЁ не подтверждаются.
В общем, изменяется только тот реквизит, перед которым указано
.ТекущийЭлемент().
Abadonna Написал:
-------------------------------------------------------
> Проверил специально: Контрагент.ТекущийЭлемент().ПолнНаименование
> изменяет ТОЛЬКО полное наименование при печати, не влияя на Наименование (ктр. я тоже поменял).
Ты не проверял такую ситуацию? Сначала обращаещся к Контрагент.ТекущийЭлемент().ПолнНаименование затем Контрагент.ПолнНаименование. При втором обращении будет старое значение или новое?
Abadonna Написал:
-------------------------------------------------------
> Да и вообще, изменять элемент лучше всего через документ, а не "на
> строне", тогда и голову забивать не надо как оно и что...
Во-во. Для этого существует специальная кнопочка "О", про которую ты сказал, что она не в теме.
> Ты не проверял такую ситуацию? Сначала обращаещся
> к Контрагент.ТекущийЭлемент().ПолнНаименование
> затем Контрагент.ПолнНаименование. При втором
> обращении будет старое значение или новое?
Ты знаешь, не поленился и проверил (кстати, остальные вместо того чтобы гадать, могли сделать тоже самое, у меня 10 сек. ушло).
При втором обращении - старое значение.
>Для этого существует специальная кнопочка "О", про которую ты сказал, что она не в теме.
В контексте вопроса O-Planet она действительно не в теме ;)
И открою тебе страшную тайну - я не знаю ни одну типовую конфигурацию ;). Для меня 1С - это 1CV7s.exe
Abadonna Написал:
-------------------------------------------------------
> Ты знаешь, не поленился и проверил (кстати, остальные вместо того чтобы гадать, могли сделать
> тоже самое, у меня 10 сек. ушло). При втором обращении - старое значение.
И какой из этого можно сделать вывод?
> В контексте вопроса O-Planet она действительно не в теме
А сейчас она в теме?
> И открою тебе страшную тайну - я не знаю ни одну типовую конфигурацию . Для меня 1С - это 1CV7s.exe
Народ, подскажите пожалуйста как сделать группировку Тз, когда в ней необходимо выделить несколько групп, имеющих иерархическую структуру подчиненности. Примерно так выглядит:
Тз.Колонка1
____ Тз.Колонка2
_______Тз.Колонка3
Yне очень понятно что имелось в виду.
1. используй ТЗ, вложенную в ТЗ
2. смотри вариант вывода ТЗ в сложной иерархии на примере
http://infostart.ru/projects/522/?ref=174
Сhe Burashka Написал:
-------------------------------------------------------
> вот задачка правильная и решение
Меня посмшила такая конструкция:
Асилить
флЕстьПеременная = 1;
Ниасилил
флЕстьПеременная = 0;
ХватитАсиливать;
Приколитесь, но я решил эту задачу:
Процедура Сформировать()
глКаталогПечФорм=глКаталогПечФорм;
Если СокрЛП(глКаталогПечФорм)="" Тогда
Сообщить("Переменной нет");
Иначе
Сообщить("Переменная есть");
КонецЕсли;
КонецПроцедуры
Проверил в пустой базе и стандартной бухне - кажет, как и ожидал.
Оговорочка: глКаталогПечФорм в глобальнике присваивается значение, иначе бы не работало
Посмотрите наткнулся на интересные строки, ничего понять не могу, может кто подскажет что бы это значило "CVTGroupings":
ОбГруппировки = "CVTGroupings";
Если СоздатьКласс (ОбГруппировки) = -1 Тогда
Сообщить ("Ошибка создания объекта: CVTGroupings", "!!!");
Возврат;
КонецЕсли;
Если флВыводПоПоставщикам = 1 Тогда
Если ОбГруппировки.Добавить ("Пост") = -1 Тогда
Сообщить ("Ошибка добавления группировки", "!!!");
Возврат;
КонецЕсли;
КонецЕсли; //
Из раздела "мелких хитростей".
Например, на форме есть список значений и кнопки для перемещения элементов списка вверх/вних (например: задание порядка группировок в типовыой ТиС). На кнопках висит процедур Сдвиг(1) = вниз или Сдвиг(-1) = вверх.
Теперь в процедуре надо проверить кучу всяких условий - есть ли элементы в списке, имеет ли смысл вообще двигать если 1 элемент, спозиционирована ли текущая строка в списке значений и прочая всяхая фигня. Будем делать проще, напишем:
Код
//*************************************************************
Процедура Сдвиг(Направление=1)
Попытка СЗ.СдвинутьЗначение(Направление,СЗ.ТекущаяСтрока());
Исключение
КонецПопытки;
КонецПроцедуры //Сдвиг()
//*************************************************************
Процедура тбДвигатьСтроку(Направление, Объект) Экспорт
ТекПоз = Объект.ТекущаяСтрока();
Если ТипЗначенияСтр(Объект) = "ТаблицаЗначений" Тогда
КолСтр = Объект.КоличествоСтрок();
Иначе
КолСтр = Объект.РазмерСписка();
КонецЕсли;
Если ТекПоз <= 0 Тогда
Возврат;
КонецЕсли;
Если (ТекПоз = 1) и (Направление = -1) Тогда
Возврат; // нельзя двигать вверх самую верхнюю строку
КонецЕсли;
Если (ТекПоз = КолСтр) И (Направление = 1) Тогда
Возврат; // нельзя двигать вниз самую нижнюю строку
КонецЕсли;
Если ТипЗначенияСтр(Объект) = "ТаблицаЗначений" Тогда
Объект.СдвинутьСтроку(Направление, ТекПоз);
Иначе
Объект.СдвинутьЗначение(Направление, ТекПоз);
КонецЕсли;
Если Направление = 1 Тогда
Объект.ТекущаяСтрока(ТекПоз+1);
Иначе
Объект.ТекущаяСтрока(ТекПоз-1);
КонецЕсли;
КонецПроцедуры // Конец Процедуры тбДвигатьСтроку()
Согласен - здесь я маненько перемудрачил... Это всегда быват, когда надумал сделать нечто универсальное и начинаешь из пальца высасывать - а что б это еще этакое заковыристое добавитть....
да, это частенкьо, кода на 20 строк ни на 250 строк обвески - подстраховки, проверки на всяк.случай, защита от дурака и прочее - стока времени отнимает...
А мне чисто интуиция подсказывает, что конструкциями "Попытка - Исключение" лучше не злоупотреблять. Не знаю, почему, может бзик такой, а может, оно на что-то там влияет на самом деле. Это ведь отработка аварийной ситуации фактически.
2O-Planet: это скорее "бзик". Замечательная конструкция и очень удобная, например
Попытка
Цена=Сумма/Количество;
Исключение
Цена=0;
КонецПопытки
И не надо проверять, не получилось ли у нас в результате чего-то Количество=0....
Жаль, что в 1С не сделали еще блок финализации
Попытка
Исключение
Обязательно
КонецПопытки
Согласен с Абадонной - конструкция весьма полезная и по компактности намного изящнее проверки условий. Если б можно было выставлять оценку за посты, без раздумий добавил бы Че единичку. Сам часто пользуюсь методом, предложенным Абадонной, а не допер, что можно подобное использовать и для сдвигов в СЗ и ТЗ. Вот воистину - программист, не тот, кто быстро 1000 строк кода наберет, а тот, кто мыслит, как программист, а это уже дар или талант, если хотите.
Абадонна, а ведь это идея: написать свою функцию попытки и вклепать туда часть кода, который ВСЕГДА должен выполнятся. Надо будет обкумекать эту идейку... Хотя. Погодь. Если он выполняется всегда, то распоожив его после попытки он и будет выполнятся всегда. Или е чего-то не вкурил?
2support
А вот хорошо бы было, если бы в мыле "получено новое сообщение по подписанной теме" еще бы и текст этого сообщения приходил (как в комментариях к разработкам). Что б лишний раз на сайт не залезать...
Abadonna Написал:
-------------------------------------------------------
> 2support
> А вот хорошо бы было, если бы в мыле "получено
> новое сообщение по подписанной теме" еще бы и
> текст этого сообщения приходил (как в комментариях
> к разработкам). Что б лишний раз на сайт не
> залезать...
Я то ее узнал. Когда ты предложил идею, я сразу о делфи подумал. Но вот кажется она несколько избыточной. Честно говоря, что-то не могу придумать область применения. В смысле впихать код в Обязательно, а не после попытки. Разве что во вложенных попытках...
Для 1С, наверное, избыточна. А вот если работать с памятью напрямую, тогда без нее вилы:
try
GetMem(buffer,500000)
except
end;
Если в исключении прога зависла/вылетела поимеем в винде захваченный кусок памяти.
А если
try
GetMeme(buffer,500000)
finally
FreeMem(buffer)
end;
память в любом случае освободится
Да уж, пожалуй такая конструкция в 1с очень бы не помешала.
А вообще сейчас разворачивается проект Апельсин, но опять же на движке 1С и с ее недостатками - вот если бы хотя бы Оперативный учет зафигачить на делфи...
Объясню, почему мне эти "попытки" не нравятся. Они отрабатывают фактически аварию, возникшую на уровне ЦП. С такой аварией масса чего связана опять же, на уровне ОС. Наверняка конструкция с ошибкой работает куда медленнее условия.
>Они отрабатывают фактически аварию, возникшую на уровне ЦП
В приличных языках существует даже понятие искуственной генерации исключений типа raise exception.
Никакой особой "аварии" на уровне ЦП не происходит, просто он тебя мягко отфутболивает с генерацией соответствующего кода ошибки
Абадонна прав, как всегда: генерация исключения есть другими словами генерация исключительной ситуации и в системе они возникают сплошь и рядом. Когда мы взводим таймер мы тем самым провоцируем запланированную исключительную ситуацию. Если по-русски, то исключительная ситуация есть некое событие в системе (плохое или хорошее - отдельная тема) которое м.б.: прерывание от внешнего устройства, исключительная ситуация среды выполнения, событие по таймеру и т.д. и т.п. А если по большому счету, то вся работа операционки построена на событиях и их обработках. Даже набирая этот текст и введя Энтер я провоцирую событие от клавиатуры. Так ничего страшного в этом нет.
Форма.ИспользоватьЗакладки(1);
Форма.Закладки.ДобавитьЗначение(" Основной ");
Форма.Закладки.ДобавитьЗначение(" Настройка ");
ПриВыбореЗакладки(1," Основной ");
Показать полностью
- на каком-то этапе/условии необходимо закрыть "несанкционированный" выход юзера с какой-нибудь закладки.
Делаем просто: выход с закладки блокируем в одно движение:
Код
Форма.ИспользоватьЗакладки(0);
Показать полностью
- на форме остануться только элементы текущей закладки, сами закладки - отсутствуют.
Можно и так:
Перем Флаг;
Процедура ПриВыбореЗакладки(Номер,Значение)
Если Флаг=1 Тогда Возврат; КонецЕсли;
....................................................................
Закладки все на месте, а элементы только текущего слоя
вот тут случаем напомнили мне мою же мелкую полезность...
касается загрузки из экселя..
Идея проста: открываем в Экселе, преобразуем в ДБФ, грузим из ДБФа.
В примере, приведенном ниже - прайс с шапкой в 11 строк, в 12 - заголовки столбцов на русском, код - в 1 колонке, цена - в 6 колонке (надо еще посмотреть, как эксель будет преобразовывать в ДБФ рассчитываемые ячейки).
Итого: прайс в 9000 строк из экселя грузится порядка 40 секунд, после преобразования в ДБФ - 1-2 сек.
Пример тестового кода
Abadonna Написал:
-------------------------------------------------------
> 2O-Planet: это скорее "бзик". Замечательная конструкция и очень удобная, например
> Попытка
> Цена=Сумма/Количество;
> Исключение
> Цена=0;
> КонецПопытки
> И не надо проверять, не получилось ли у нас в
> результате чего-то Количество=0....
Конструкция Попытка-Исключение - замечательная. Не спорю. Но это не лекарство от всех болезней.
Считаю, что программисты Раруса злоупотребляют этой конструкцией. Например, при проверке есть ли реквизит объекта или нет. Программисты 1С предпочитают использовать объект метаданные.
ИМХО код от одинэсовых программистов красивее чем от Раруса.
Кроме того, конструкции Транзакция и Попытка бывает сложно подружить между собой.
> ИМХО код от одинэсовых программистов
учился по нему.. книжек не было.. ничего не было..
открывал и смотрел... код написан ясно - это существенно помогло...