powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Комьюнити против макроподстановк&..Продолжение
25 сообщений из 43, страница 1 из 2
Комьюнити против макроподстановк&..Продолжение
    #35086801
CTAC-KO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Привет!

Вобщем я всегда думал что макроподстановка - это нормальная практика. Но специалисты оказывается стараются ее не применять или применять только в исключительных случаях. Мне уже объяснили и показали на одном примере как ее не применять, более того, как выяснилось в Объектно-Ориентированном Программировании не используют обращение к объектам через их имя (что я и делал с помощью макроподстановки), а делают это через ссылки на объекты. Пример как избавиться от макроподстановки и в целом оптимизировать свой код на моем примере можно посмотреть здесь , где получилось 2 варианта решения от пользователей Dima_T и прошелмимо. Будем считать сие началом этой темы, так как тема той ветки изначально была несколько иная.

Я бы хотел продолжить эту тему и просить Вашей помощи еще в несколькольких задачах, т.к. если со ссылками на объекты теперь понятно, то возник вопрос - а как быть с необъектами?

Итак, у меня похожая задача, только в тот раз я к текстбоксам объекты лепил, а теперь мне нужен фильтр. Я пошел схожим путем и для каждого своего листбокса (лепленного на ходу к едитбоксам так же как лейбл-счетчик в прошлом примере) создавал глобальную переменную с именем родитель+объект.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
* превращаем адрес(иерархию) объекта в имя переменной
   lcFilterVar = "gc"+CHRTRAN(SYS( 1272 ,loWordsList),".","")
   * объявляем глобальную переменную для фильтра
   IF VARTYPE(&lcFilterVar) = "U"
      PUBLIC &lcFilterVar
      * в пропертя объекта схороним имя переменной-фильтра
      this.WordsFilterVar = m.lcFilterVar
   ENDIF
   * запоминаем значение для фильтра в глобальной переменной
   &lcFilterVar = LOWER(ALLTRIM(this.Value))
   * Выбираем область и ставим фильтр
   lcWordsTable = this.WordsTable
   lcWordsField = this.WordsField
   * устанавливаем фильтр по глобальной переменной
   SET FILTER TO LOWER(&lcWordsField) = &lcFilterVar IN (lcWordsTable)
на методе Destroy объекта, глобальная переменная удаляется
Код: plaintext
1.
2.
3.
4.
5.
IF NOT EMPTY(this.WordsFilterVar)
      lcFilterVar = this.WordsFilterVar
      IF VARTYPE(&lcFilterVar)#"U"
         RELEASE &lcFilterVar
      ENDIF   
   ENDIF
я уже попробовал тут применять EVALUATE(), но безуспешно... До того пробовал хранить значение для фильтра в пропертях объекта и тоже безуспешно. Возможно задача с фильтром вообще иначе решается?
...
Рейтинг: 0 / 0
Комьюнити против макроподстановк&..Продолжение
    #35086859
прошелмимо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вот с фильтрами
как раз и так и делают

только паблик тебе там сто лет не нужен
если выполнить макроподстановкой заранее созд-ю команду

Код: plaintext
1.
2.
3.
use (tcParamsTable) in  0  alias (this.cAlias+'par') again 
local lcCmd
lcCmd = 'set filter to id='+alltrim(str(tnID))

но ....

set filt - это для ленивых, или не знающих иных приемов ...
я так делаю если точно знаю что размер ист-ков будет оч.маленький
и влом думать и писать правильный код

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

недостатки set filt - оч.медленно работает
http://www.sql.ru/forum/actualthread.aspx?tid=380474&hl=set+filter
...
Рейтинг: 0 / 0
Комьюнити против макроподстановк&..Продолжение
    #35086869
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Опять нагородил Это тремя строчками пишется:
Код: plaintext
1.
2.
local lcFilter
lcFilter = 'lower(' + this.WordsField + ') = "' + chrtran(LOWER(ALLTRIM(this.Value)), '"', '') + '"'
SET FILTER TO &lcFilter IN (this.WordsTable)

SET FILTER TO - это одно из тех исключений, где удобно макроподстановку использовать, т.к. ее обход требует много кода, глобальных переменных (можно заменить на свойства объекта _screen) или доп.свойств формы (если PrivateDataSession)

SET FILTER зашивать в библиотеку - не лучший вариант. Его не желательно использовать (много минусов), но иногда это бывает наилучший вариант.

PS В Destroy() - ошибку создаешь. Переменную удалил, а SET FILTER ее использующий оставил.
...
Рейтинг: 0 / 0
Комьюнити против макроподстановк&..Продолжение
    #35086887
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
VARTYPE(&lcFilterVar) = "U"
всегда .F. или ошибка если переменной не существует. Правильно:
Код: plaintext
TYPE(lcFilterVar) = "U"
...
Рейтинг: 0 / 0
Комьюнити против макроподстановк&..Продолжение
    #35086896
прошелмимо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
да, действит-но
лепишь макроподстановки где нужно и не нужно без разбору

Код: plaintext
1.
2.
3.
      IF VARTYPE(lcFilterVar)="С"
             RELEASE lcFilterVar
      ENDIF   

2Dima T
у него ош-ка не в-ся, т.к. глоб. перем-я не убивается
...
Рейтинг: 0 / 0
Комьюнити против макроподстановк&..Продолжение
    #35086901
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T
Код: plaintext
VARTYPE(&lcFilterVar) = "U"
всегда .F. или ошибка если переменной не существует. Правильно:
Код: plaintext
TYPE(lcFilterVar) = "U"

Наврал немного, ошибка только при работе с объектами.
...
Рейтинг: 0 / 0
Комьюнити против макроподстановк&..Продолжение
    #35086997
CTAC-KO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TPS В Destroy() - ошибку создаешь. Переменную удалил, а SET FILTER ее использующий оставил.
у меня там на самом деле так (просто неполностью выложил):
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
   SELECT (this.WordsTable)
   SET FILTER TO
   * убираем из памяти глобальную переменную фильтра
   IF NOT EMPTY(this.WordsFilterVar)
      lcFilterVar = this.WordsFilterVar
      IF VARTYPE(&lcFilterVar)#"U"
         RELEASE &lcFilterVar
      ENDIF   
   ENDIF
...
Рейтинг: 0 / 0
Комьюнити против макроподстановк&..Продолжение
    #35087028
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CTAC-KO Dima TPS В Destroy() - ошибку создаешь. Переменную удалил, а SET FILTER ее использующий оставил.
у меня там на самом деле так (просто неполностью выложил):
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
   SELECT (this.WordsTable)
   SET FILTER TO
   * убираем из памяти глобальную переменную фильтра
   IF NOT EMPTY(this.WordsFilterVar)
      lcFilterVar = this.WordsFilterVar
      IF VARTYPE(&lcFilterVar)#"U"
         RELEASE &lcFilterVar
      ENDIF   
   ENDIF

Думаю ты уже догадался что достаточно первых двух строк твоего кода
...
Рейтинг: 0 / 0
Комьюнити против макроподстановк&..Продолжение
    #35087062
CTAC-KO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TОпять нагородил Это тремя строчками пишется:
Код: plaintext
1.
2.
local lcFilter
lcFilter = 'lower(' + this.WordsField + ') = "' + chrtran(LOWER(ALLTRIM(this.Value)), '"', '') + '"'
SET FILTER TO &lcFilter IN (this.WordsTable)
наподобии у меня и было сразу (без chrtran). Только проблема в том, что значение для фильтра может включать и кавычки и апостроф, причем даже одновременно. короче с chrtran - не подходит. либо тогда нужно chrtran включать в левую часть фразы тоже. К примеру значение в поле може быть
Код: plaintext
ТОВ "Колхоз им. Жанны Д'Арк" 
...
Рейтинг: 0 / 0
Комьюнити против макроподстановк&..Продолжение
    #35087133
CTAC-KO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
итого, меньше макроподстановок + оптимизация =
Код: plaintext
1.
2.
3.
4.
   LOCAL lcFilterStr
   lcFilterStr = "LOWER(CHRTRAN("+this.WordsField+"," +'""'+ ",'')) = LOWER(CHRTRAN('"+ALLTRIM(this.LastWord)+"'," +'""'+ ",''))"
   * ставим фильтр
   SET FILTER TO &lcFilterStr IN (this.WordsTable)
...
Рейтинг: 0 / 0
Комьюнити против макроподстановк&..Продолжение
    #35087141
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CTAC-KO Dima TОпять нагородил Это тремя строчками пишется:
Код: plaintext
1.
2.
local lcFilter
lcFilter = 'lower(' + this.WordsField + ') = "' + chrtran(LOWER(ALLTRIM(this.Value)), '"', '') + '"'
SET FILTER TO &lcFilter IN (this.WordsTable)
наподобии у меня и было сразу (без chrtran). Только проблема в том, что значение для фильтра может включать и кавычки и апостроф, причем даже одновременно. короче с chrtran - не подходит. либо тогда нужно chrtran включать в левую часть фразы тоже. К примеру значение в поле може быть
Код: plaintext
ТОВ "Колхоз им. Жанны Д'Арк" 


Сделай замену двойной кавычки на одинарную и включи в обе части одновременно:
Код: plaintext
lcFilter = 'chrtran(lower(' + this.WordsField + '), ["],' + "[']" + ') = "' + chrtran(LOWER(ALLTRIM(this.Value)), ["], [']) + ')" '

Только читать этот код из кавычек невозможно. Проще функцию причесывания кавычек сделать
Код: plaintext
1.
2.
func DoloyKavichki
lpara tcText
return chrtran(lower(alltrim(tcText)), ["], ['])
и ее использовать:
Код: plaintext
lcFilter = 'DoloyKavichki(' + this.WordsField + ') = "' + DoloyKavichki(this.Value) + '"'
...
Рейтинг: 0 / 0
Комьюнити против макроподстановк&..Продолжение
    #35087215
CTAC-KO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
хорошо, теперь о неиспользовании фильтра в фелом. Ну а если уже и юзать, то обязательно индекс надо будет приделать.
Если не юзать фильтр вообще, то нужно будет каждый раз делать выборку (там где фильтр ща). Если у меня это клиент-сервер, то мне тогда лучше один раз выбрать сразу все, а затем оттудова постоянно выборки делать (для скорости которых сиравно нужен индекс) или каждый раз с сервера спрашивать?
...
Рейтинг: 0 / 0
Комьюнити против макроподстановк&..Продолжение
    #35087230
прошелмимо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
.. this.Value ...

SET FILTER TO &lcFilterStr IN (this.WordsTable)

ох-ох-ох

моделим ош-ку

запускаем все это добро
под разработкой

жмем Ctrl+F2
в коммандном окне пишем
sele (...)
brow
...
Рейтинг: 0 / 0
Комьюнити против макроподстановк&..Продолжение
    #35087410
CTAC-KO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
прошелмимо.. this.Value ...

SET FILTER TO &lcFilterStr IN (this.WordsTable)

ох-ох-ох

моделим ош-ку

запускаем все это добро
под разработкой

жмем Ctrl+F2
в коммандном окне пишем
sele (...)
brow с этим понятно - просто добавить в мп и все:
Код: plaintext
1.
2.
3.
4.
   * строим значение для фильтра в локальной переменной
   lcFilterStr = 'LowerAndNoQuotes('+this.WordsTable +'.'+ this.WordsField+') = "'+LowerAndNoQuotes(ALLTRIM(this.Value))+'" IN ' +this.WordsTable

   * устанавливаем фильтр по локальной переменной
   SET FILTER TO &lcFilterStr
функция:
Код: plaintext
1.
2.
3.
4.
* функция перевода в нижний регистр + замена всех кавычек на апостроф
FUNCTION LowerAndNoQuotes
LPARAMETERS tcText
RETURN CHRTRAN(LOWER(m.tcText), ["], ['])
ENDFUNC
а вот еще вопрос по ходу, если своя функция. У Dima_T параметр описан так:
Код: plaintext
1.
func DoloyKavichki
lpara tcText
а если написать так:
Код: plaintext
func DoloyKavichki(tcText)
то параметр tcText перестанет быть локальным и при возврате из функции не релизанеццо?
...
Рейтинг: 0 / 0
Комьюнити против макроподстановк&..Продолжение
    #35087445
прошелмимо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ох, шаман

так не нравится???
Код: plaintext
1.
2.
3.
4.
5.
6.
 
local lcFilterStr
lcFilterStr = 'set filter to LowerAndNoQuotes('+this.WordsTable +'.'+ this.WordsField+') = "'+LowerAndNoQuotes(ALLTRIM(this.Value))+'" IN ' +this.WordsTable

* устанавливаем фильтр по локальной переменной
&lcFilterStr


посмотри в сторону конструктора-построителя запросов на сервер
с ограничением выборки
...
Рейтинг: 0 / 0
Комьюнити против макроподстановк&..Продолжение
    #35087472
CTAC-KO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
если Вам еще не надоело, переходим к еще одному моему "шедевру" полета м0кроподстановочной мысли
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
      lnFCount = AFIELDS(arrFields)
      IF ASCAN(arrFields,"G", 1 ,m.lnFCount, 2 )# 0 
         *MESSAGEBOX("Achtung! General Fields!")
         *SUSPEND 
         lsSQLConvStr="SELECT"
         FOR lnF =  1  TO lnFCount
             field_name = arrFields(m.lnF, 1 )
             field_type = arrFields(m.lnF, 2 )
             DO CASE
                CASE field_type = "G"
                lsSQLConvStr = m.lsSQLConvStr +" "+ "CAST(CAST("+LEFT(m.field_name, 10 )+" AS W) AS M) AS "+m.field_name

                CASE field_type = "C"
                lsSQLConvStr = m.lsSQLConvStr +" "+ "RTRIM("+LEFT(m.field_name, 10 )+") AS "+m.field_name
                
                OTHERWISE
                lsSQLConvStr = m.lsSQLConvStr +" "+LEFT(m.field_name, 10 ) + " AS "+m.field_name
             ENDCASE
             IF lnF # lnFCount
                lsSQLConvStr = m.lsSQLConvStr +","
             ENDIF
         ENDFOR
         *SUSPEND 
         lcTempName = "tmp"+SYS( 3 )
         lcTempDBF = SYS( 2023 ) + "\" + m.lcTempName +".dbf"
         lsSQLConvStr = lsSQLConvStr + " FROM " + m.lcTempName + " INTO CURSOR " + m.lcCursor + " READWRITE"
         ERASE (lcTempDBF)
         COPY TO (lcTempDBF)
         *USE IN (m.lcCursor)
         USE (lcTempDBF) &&IN  0  &&ALIAS m.lcTempName
         &lsSQLConvStr 
         USE IN (m.lcTempName)
         ERASE (lcTempDBF)
         *MESSAGEBOX(lsSQLConvStr )
      ENDIF
      
      SELECT (lcCursor)
      * Реплюсинх NULL во всех полях по соотв.
      lnFCount = FCOUNT()
      FOR lnF =  1  TO m.lnFCount
          lcFName = FIELD(m.lnF)
          lcFType = TYPE(m.lcFName)
          DO CASE
             CASE m.lcFType = "D" OR m.lcFType = "T" 
                REPLACE ALL &lcFName WITH NVL(&lcFName,{..})
             CASE m.lcFType = "N"
                REPLACE ALL &lcFName WITH NVL(&lcFName, 0 )
             CASE m.lcFType = "C"
                REPLACE ALL &lcFName WITH NVL(&lcFName,'')
             CASE m.lcFType = "M"
                REPLACE ALL &lcFName WITH NVL(&lcFName,'')
          ENDCASE
      ENDFOR
первый блок сделан для того, чтобы возвращенное с SQL поле типа General перевести в Memo (еще хотел CHAR перевести на VARCHAR, но пока не получилось, впрочем и не шибко-то надо), второй для замены возвращенных NULL-ов на менее пужающие пустоты :)

2прошелмимо - последнее, по-моему, не содержит какой-либо существенной разницы, что все в мп, что часть, или?
...
Рейтинг: 0 / 0
Комьюнити против макроподстановк&..Продолжение
    #35087517
CTAC-KO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
это так скать, третий клинический случай - не объект, не фильтр, а обращение к полям бд и формирование командной строки.
...
Рейтинг: 0 / 0
Комьюнити против макроподстановк&..Продолжение
    #35087568
CTAC-KO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
прошелмимопосмотри в сторону конструктора-построителя запросов на сервер
с ограничением выборки я-то понимаю как ограничить выборку, но вот есть ли смысл в таком ключе - юзер набирает какой-то текст в едитбоксе. В методе interactivechange, когда набрано 4 символа срабатывает код, который выдает в листбоксе возможные варианты слов, начинающихся с этих 4х букаф. Так вот, получаеццо, каждые 4 буквы я буду ломиццо с запросом на сервер...
...
Рейтинг: 0 / 0
Комьюнити против макроподстановк&..Продолжение
    #35087612
CTAC-KO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
кое-что уже заменил на evaluate()
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
lnFCount = FCOUNT()
      FOR lnF =  1  TO m.lnFCount
          lcFName = FIELD(m.lnF)
          lcFType = TYPE(m.lcFName)
          DO CASE
             CASE m.lcFType = "D" OR m.lcFType = "T" 
                REPLACE ALL &lcFName WITH NVL(EVALUATE(lcFName),{..}) &&lcFName,{..})
             CASE m.lcFType = "N"
                REPLACE ALL &lcFName WITH NVL(EVALUATE(lcFName), 0 ) &&lcFName, 0 )
             CASE m.lcFType = "C"
                REPLACE ALL &lcFName WITH NVL(EVALUATE(lcFName),'') &&lcFName,'')
             CASE m.lcFType = "M"
                REPLACE ALL &lcFName WITH NVL(EVALUATE(lcFName),'') &&lcFName,'')
          ENDCASE
      ENDFOR
...
Рейтинг: 0 / 0
Комьюнити против макроподстановк&..Продолжение
    #35087690
прошелмимо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ох

ты наверно весь фокс перепишешь на фокс-же
только с макроподстановками

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


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
/*
create table #t (id int, value varchar(10))

insert into #t (id, value)
	values (null,null)
*/

select  id=isnull(id, 0 ),
	value=isnull(value,'')
  from #t

что их на стороне клиента-то шарохать?
тем более, что чаще всего они наоборот нужны!!!
...
Рейтинг: 0 / 0
Комьюнити против макроподстановк&..Продолжение
    #35087700
прошелмимо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
юзер набирает какой-то текст в едитбоксе.

счаз

посмотри в сторону визардов
пример есть в upsize wizard

посмотри
на виз-е средства-построители запросов
...
Рейтинг: 0 / 0
Комьюнити против макроподстановк&..Продолжение
    #35087714
CTAC-KO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
прошелмимоох
ты наверно весь фокс перепишешь на фокс-же
только с макроподстановками

прошелмимоне допустить нулл в рез-м курсоре
можно правильно написав запрос
та да, но задача показать как не делать мп в таких случаях, т.е. обращение к полям бд.
...
Рейтинг: 0 / 0
Комьюнити против макроподстановк&..Продолжение
    #35087744
CTAC-KO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
прошелмимопосмотри в сторону визардов
пример есть в upsize wizard
посмотри
на виз-е средства-построители запросовdbc у миня нет. а wzupsize.app - как смотреть?
...
Рейтинг: 0 / 0
Комьюнити против макроподстановк&..Продолжение
    #35087753
прошелмимо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
....\vfp9\Tools\xsource\
...
Рейтинг: 0 / 0
Комьюнити против макроподстановк&..Продолжение
    #35087782
прошелмимо
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторта да, но задача показать как не делать мп в таких случаях, т.е. обращение к полям бд.

я для себя всегда знаю имена полей и
пишу без макроподстановок

если это класс унив-й, то наследую,
и меняю четко нужные места, приспосабливая класс
под конкр-ю стр-ру

если что-то должно тянуться,
то придумываю генер-ры с послед-й компиляцией
и хранением и вып-ем скомпил-го байт-кода
...
Рейтинг: 0 / 0
25 сообщений из 43, страница 1 из 2
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Комьюнити против макроподстановк&..Продолжение
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]