Страницы: 1 2 След.
RSS
Возможно ли переназначить WorkSheets(b) в WorkSheets(c) ?
 
Добрый день.
Подскажите, а можно ли каким-то образом сделать так, чтобы конструкция WorkBooks(a).WorkSheets(b) стала эквивалентна записи WorkBooks(a).WorkSheets(с) ?
Т.е, чтобы при обращении к методам и свойствам WorkSheets(b) фактически шло обращение к одноименным методам и свойствам другого листа?
Изменено: Neufazendnik - 21.06.2018 23:52:10
 
Свойства и методы у ВСЕХ листов одинаковы. Вы лучше опишите ЗАДАЧУ, а не СПОСОБ, которым пытаетесь ее решить
Согласие есть продукт при полном непротивлении сторон
 
Задача не переделывать код бесчисленного числа подпрограмм, которые ссылались на некоторые листы одного файла. Файл разросся. Листы решено динамически выгружать в отдельные файлы. Но не все, а те, что стали переполнены данными. Ситуация динамично меняется по мере заполнения БД, поэтому какие листы уже выгружены, а какие остаются в исходном файле - заранее в коде предусмотреть невозможно.  Кроме того, по некоторым причинам после выгрузки в отдельный файл, лист с данными из исходного файла полностью не удаляется, а остается в качестве шаблона, не заполненного данными.
Поэтому перед каждым обращением к очередному листу надо делать блок анализа, где находятся данные этого листа и либо брать их с листа исходного файла либо брать их с одноименного листа стороннего файла. Чтобы не лопатить весь код имеющихся подпрограмм, мне проще в нескольких местах делать подмену объектных переменных, содержащих ссылку на какой-либо лист.

Однако есть сложность. Особенно в ранних подпрограммах не использовались переменные типа set a=workbooks(n).worksheets(m).cells  r=a(c,d)
а были прямые обращения r=workbooks(n).worksheets(m).cells(c,d)
Такого кода не мало. И разобраться, какой еще нужен, а какой нет смысла переделывать - оно того не стоит. Проще глобально переопределять workbooks(n).worksheets(m) перед работой подпрограмм.
 
Код
Dim iSh As Worksheet
'перебираем все листы в активной книге
For Each iSh In Worksheets
    If iSh .... Then    'тут анализируем лист
        'како-то код
    End If
Next

Согласие есть продукт при полном непротивлении сторон
 
Цитата
Neufazendnik написал:
не переделывать код бесчисленного числа подпрограмм, которые ссылались на некоторые листы одного файла
Для таких вещей давно придумали константы. Создаете константу с именем нужного листа(или чего там еще) и обращаетесь к ней везде, где надо обратиться к листу с таким именем. Правка кода потом сводится к замене одной строки.
На данный же момент у Вас только один путь: Ctrl+H и ReplaceAll по CurrentProject. Указываете имя листа в кавычках, которое заменить и так же в кавычках на что заменить.
Хотя могу ошибаться - уж очень как-то расплывчато и непонятно(для меня) все звучит.
Изменено: Дмитрий Щербаков - 22.06.2018 09:45:26
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Цитата
Дмитрий Щербаков написал:
Указываете имя листа в кавычках, которое заменить и так же в кавычках на что заменить.
Дмитрий Щербаков, Этот путь неприемлем, потому что прямая нотация в виде названия листа в кавычках в подпрограммах ни где не фигурирует. Листы везде вызываются как раз через константы. Только вот в моем случае это даже не константы, а отдельные переменные. Причинами тому является то, что многие процедуры и функции у меня универсальны. Они заранее не знают, с каким листом будут работать. Имя листа им передается в качестве одного из параметров. Таким образом одно и то же название листа может в разных подпрограммах быть заменено тысячами разных переменных и машинально заменить через ctrl-F не представляется возможным.
Изменено: Neufazendnik - 22.06.2018 10:21:17
 
Покажите файл-пример с Вашими листами и процедурами их обработки
Согласие есть продукт при полном непротивлении сторон
 
Вот пример обрабатываемого листа. Только строк обычно десятки тысяч. Просто срезал, т.к на форум больше 100Кб не грузится.
Изменено: Neufazendnik - 22.06.2018 10:57:06
 
Цитата
Neufazendnik написал:
прямая нотация в виде названия листа в кавычках в подпрограммах ни где не фигурирует
Тогда вообще неясно что Вы хотите сделать. Если и так все через переменные и константы - значит надо просто переписывать логику кода под текущие требования. Других вариантов нет.
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Цитата
Neufazendnik написал:
многие процедуры и функции у меня универсальны. Они заранее не знают, с каким листом будут работать. Имя листа им передается в качестве одного из параметров
Вот здесь не могу понять: а почему сразу не передавать имя нужного листа, вместо того, чтобы передать имя другого, а затем подменять его?
 
Юрий М, Проблема в существовании таблиц(в моей нотации они называются типами и пронумерованы), не умещающихся на единственном листе экселя. К тому же, есть возможность зачистки данных, поэтому выборка данных по их индексу не тривиальна. К примеру, приложенная мною в функция служит для того, чтобы вернуть как раз объекнтую переменную - лист хранения данных с заданным индексом данных. В качестве результата работы функции возвращается номер строки на этом листе. И далее, уже другие подпрограммы могут делать прямой запрос к данным по возвращенной ссылке на лист и номеру строки на этом листе. Тут все красиво. Переделать все не сложно, чтобы возвращалась объектная ссылка ссылка на любой лист, вне зависимости от того, в каком он файле.
Однако, некоторые процедуры имеют свой механизм прямого обращения к данным листов. Эти процедуры тоже универсальны и обращаются к листам с различными именами, которые на этапе написания кода не всегда предопределены и в процессе работы динамически передаются. И вот с ними то вся затыка. В каждой из процедур пересматривать логику - мне жизни не хватит разобраться. Проще, как только какой-то лист переходит из общего файла в независимый, взять и для всего контекста переменных глобально переопределить вот как-нибудь так:
set workBooks(a).workSheets(b) = workBooks(e).workSheets(b)
Изменено: Neufazendnik - 22.06.2018 11:35:02
 
Цитата
Юрий М написал:
Вот здесь не могу понять: а почему сразу не передавать имя нужного листа, вместо того, чтобы передать имя другого, а затем подменять его?
В общем, одни и те же  по своей структуре данные могут быть расположены на разных листах, в зависимости от номера записи (у меня это называется индекс). При этом сначала база данных не велика и все данные размещаются в пределах одного файла. В какой-то момент срабатывает динамическая выгрузка (отсаживание) некоторых переполненных\разросшихся данными листов в отдельные файлы. Код то при этом обрабатывает их прежний. И нужно адаптировать старый код под работу с удаленными в отдельные файлы листами и при этом оставить старые функции работы с теми же листами, пока они еще не отделились от основного файла с данными.
 
Вижу нестыковку в Ваших сообщениях: сначала имя книги оставалось неизменным, а менялось имя листа:
Цитата
Neufazendnik написал:
чтобы конструкция WorkBooks(a).WorkSheets(b) стала эквивалентна записи WorkBooks(a).WorkSheets(с)
А теперь наоборот: имя листа неизменно, а меняется имя книги:
Цитата
Neufazendnik написал:
set workBooks(a).workSheets(b) = workBooks(e).workSheets(b)
 
Цитата
Neufazendnik написал: в нескольких местах делать подмену объектных переменных, содержащих ссылку на какой-либо лист.
Код
Sub TheRightSheet()
Dim sht As Worksheet
    Set sht = Worksheets("это_он")
'    Set sht = wsData ' обращение по внутреннему имени
    
    Call RecrptionSheet(sht)
End Sub

Sub RecrptionSheet(sht As Worksheet)
    With sht
        .Cells(5, 5).Value = 25
    End With
End Sub
 
Нестыковки нет. Это примеры возможного применения. И тот и другой вариант для меня представляет практический интерес. Тем более что механизм реализации переназначения листа должен присутствовать и там и там один и тот же, за исключением присутствия\отсутствия осложения в виде getobject
Изменено: Neufazendnik - 22.06.2018 12:34:09
 
Может быть отталкиваться от кодового имени листа?
 
vikttur, Не пойдет. Заранее, жестко безальтернативно прописать: Set sht = Worksheets("это_он") я не могу. Точнее могу и так и делал 10 лет назад, когда начинал развивать этого программного монстра. Но теперь концепция сменилась. Назрела необходимость "Это он" переместить (или не переместить -по ситуации, определяемой динамически набором обрабатваемых данных) в другую книгу. Таким образом весь код TheRightSheet() требует переработки и вызова дополнительной процедуры анализа фактического размещения листа "Это он" перед каждым вызовом Set sht = Worksheets("это_он"). Учитывая, что процедур сотни, и в каждой из них порой  по нескольку десятков конструкций типа Set sht = Worksheets("это_он") , то переписывать это все - сизифов труд. Разумнее осуществить подмену, в которой при вызове Worksheets("это_он") будет на самом деле вызываться иной лист.
 
Еще по поводу Set sht = Worksheets("это_он")
Для многих подпрограмм такого варианта вообще не применяется, потому как названия листов и их число не предопределены в качестве констант, а генерируются автоматически в процессе работы программ по правилам. Например листы хранения данных какого-то типа имеет формат N1UN2, где N1- номер типа. N2 - номер листа хранения данных. Гипотетически в БД может присутствовать лист скажем 120U4, но не факт, что он фактически присутствует в конкретной реализации БД. И не факт, что он присутствует в основном  файле БД, а не вынесен в отдельный. В общем, практически все подпрограммы оперируют именно такими листами, имена которых вычисляются на ходу.
 
Neufazendnik, сделайте перерыв в теме. Приготовьте файл-пример, по  которому помогающие смогут понять Вашу проблему и попытаться помочь. А так ("это  пойдет. то в топку вон то неправильно...") - переливание с пустого в порожнее. Всем скоро надоест.

Цитата
Neufazendnik написал: названия листов и их число не предопределены в качестве констант,
Я Вам только пример показал, как передавать лист. А как Вы его в переменную разместите - это другой вопрос. Можно же не явно прописывать, а вычислять
 
Пока БД работает в следующем режиме. Как только выясняется, что какой-то лист выгружен в отдельный файл, но его данные нужны для работы, программа копирует лист целиком назад в БД и работает с ним как будто он никуда не откреплялся. А после работы уже обратно перегружает этот лист в отдельный файл. Все бы хорошо, но большой объем перегрузок туда-сюда - не совсем рациональное решение. Хотелось бы уже не таскать листы из файла в файл а сохранив старый код работы с одним единственным файлом, все же организовать ссылки на распределенную вне его информацию.
 
Neufazendnik, почему-то у меня складывается стойкое ощущение, что Вам нужно просто вынести переменную с именем листа в сигнатуру соответствующих процедур и функций в качестве входного параметра, и уже в main'е (или где у Вас точка входа) вызывать их с нужным параметром. И всё.

А вообще, хотя VBA и не вполне ООП-язык, паттерны и рефакторинг Вам в помощь. Вся эта сверхсложная система наверняка возникла из-за некорректной архитектуры проекта, и может быть упрощена с помощью построения правильной объектной модели и, к примеру, фабричного метода.
 
дочитал... в теме 20 сообщений без смысла (извините все, кто отвечал здесь)
Neufazendnik,
см. соообщение #2, опишите не дебри, в которые Вы забрались в попытках решить задачу, а опишите задачу, которую нужно решить:
- макрос должен обработать определенный лист,
- несколько определенных листов,
- пользователь должен УКАЗАТЬ какие листы обработать,
- Ваш вариант

я так понимаю, макрос обработки листа есть, нужно только определить с какими листами в качестве параметра последовательно его вызвать
если не будет ответа на это собщение или после ответа задача все еще останется неопределенной - это сообщение должно быть автоматически причислено к предыдущим, как бессмысленное
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Цитата
Irregular Expression написал:
и уже в main'е (или где у Вас точка входа) вызывать их с нужным параметром. И всё.
Ага, вопрос только в том, где у меня точка входа?
1. Сначала отрабатывает selection_change , которая есть в любом из 10 доступных пользователю окон (называю их контекстами) для работы с данными. Все эти окна-контексты однотипны\универсальны и могут отображать что угодно - что собственно загрузит в них обработчик действий пользователя. Название и назначение колонок до загрузки в контекст данных не определено. Поведенческая реакция в каждой колонке тоже не предопределена. Она меняестся в зависимости от того, какая таблица загружена в оно.
2 selection_change любого листа контекста содержит одну единственную строку - вызов обработчика ah. Тот определяет, что хотел пользователь тем или иным перемещением по листу контекста. Меню команд нет. Действия пользователя обработчик угадывает по смещениям между ячейками и их частоте, двойному клику, нажатию tab или правой кнопки мыши. В общем, ah производит интерпретацию перемещений по листу контекста. Анализирует, в какой графе они происходили. Обращается к списку, описывающему поведенческую структуру колонок загруженного в контекст типа информации, интерпретирует, какую из доступных команд возможно запросил пользователь своими перемещениями по листу, просит подтверждение выполнения команды и вызывает процедуру, обработчик, которая должна сделать нужное пользователю действие. (таких процедур сотни)
3. Запускается процедура обработчик, которая запрашивает у пользователя детали. Например, пользователь смотрит прайс и  в некоторой ячейке таблицы видит название товара по накладным(которое отличается от прайсового). Он хочет видеть строки накладных, в которых этот товар поступал. Это уже совершенно другая таблица. Ее нужно сгенерировать в новом контексте. Процедура обработчик запрашивает детали операции. Например, показать только эти строки или вообще все строки накладных одной таблицей, в которой выделить данные.  Иногда запрос сложный.  Он требует вывода промежуточной таблицы и отметить в ней некоторые...
Не, ребята, это можно писать бесконечно. Мне проще попытаться сделать видео и показать Вам, как это все на экране выглядит, чтобы стало понятно, что это все очень не тривиально и нет тут как такового основного кода, вызывающего процедуры. Уровень вложенности - процедур 6-9. Все они друг с другом тесно взаимодействуют. Это гибридный монстр. Попробую сделать видео и выложить ссылку. Не могу я такие вещи сложные на словах описать.
 
Цитата
Neufazendnik написал: Не, ребята, это можно писать бесконечно
Вам об этом сразу писали:
Цитата
Sanja написал: Покажите файл-пример с Вашими листами и процедурами их обработки

Цитата
NeufazendnikМне проще попытаться сделать видео и показать Вам,
Вам, может, и проще, но правильнее
Цитата
vikttur написал: Приготовьте файл-пример, по  которому помогающие смогут понять Вашу проблему и попытаться помочь
Выше Вы показали пример листа, но что толку от 1000 строк с несколькими столбцами? Смотреть на красивые циферки? Пример должен показать проблему.
 
Осилил 25 сообщений.
Цитата
Уровень вложенности - процедур 6-9. Все они друг с другом тесно взаимодействуют. Это гибридный монстр.
По-моему дело здесь в архитектуре программного продукта. Она (архитектура) для того и создается, что бы было четко определено, что и где в коде происходит, с вынесением отдельных функций, примечание к коду и т.д.

Neufazendnik, разбираетесь с архитектурой, проидитесь отладчиком, прокомментируйте код. Когда поймёте, что конкретно вам необходимо, задайте конкретный вопрос, мы ответим. Сейчас (лично я) так и не понял, что нужно в конечном итоге, какая конечная цель обсуждаемого кода и что в нем не получается. Лучше вас в вашем коде никто не разберётся, да же с видео (особенно с видео, т.к. программист работает с кодом, а видео - это вспомогательный инструмент).
«Бритва Оккама» или «Принцип Калашникова»?
 
Цитата
Neufazendnik написал: Ага, вопрос только в том, где у меня точка входа?
Цитата
Уровень вложенности - процедур 6-9. Все они друг с другом тесно взаимодействуют. Это гибридный монстр.
Вы сами озвучили проблему своей программы: излишняя сложность и связанность кода, отсутствие у Вас представления о её архитектуре.
Далее необходимо осмыслить логический вывод, что поставленный Вами в начале темы вопрос - это лишь ещё один гвоздь/костыль в гроб Вашего кода, а не решение реально существующей проблемы.
Решений же тут может быть лишь два:
1) Рефакторить, если процесс "протухания" кода обратим.
2) Переписать заново, если процесс дошёл до точки невозврата, когда и Вы, и окружащие перестали понимать Вашу программу.
Чтобы дать какие-то конкретные рекомендации по рефакторингу, надо видеть код. Ни видео, ни скрины, ни Ваши пространные объяснения тут не будут информативными, всё равно как диагноз заочно ставить.
 
Цитата
Neufazendnik написал: это можно писать бесконечно.
похоже на то

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

Цитата
в любом из 10 доступных пользователю окон (называю их контекстами)
а как доступные пользователю окна называются в Excel? не листы случайно?

Цитата
содержит одну единственную строку - вызов обработчика ah
один обработчик для всех - это уже хорошо!
но если речь о событиях изменилась отметка на листе, то такой ОДИН обработчик уже есть в каждой книге:
Код
Workbook_SheetSelectionChange(Sht as Object, Rg as Range)
можно продолжать разбирать фразы из текста, но в теме уже более 20 сообщений...
как только Вы перестанете рассказывать о Вашем решении задачи, а начнете рассказывать о самой задаче - появится хоть какой-то шанс...
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
представляю если поисковые системы предложат эту тему для поиска решения в ней:
- представляю сколько нехороших слов выльется на голову автора
- на всех, кто тут отвечал (ответа-то нет)
- а следом и на сайт

уважаемые модераторы,
извините., но не пора-ли это удалять и предложить Neufazendnik, начать все сначала, с учетом замечаний

или по сути вопроса оставить тему с одним ответом:
Возможно.
Изменено: Ігор Гончаренко - 22.06.2018 15:40:57
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Игорь, я одну уже закрыл - там вообще было три вопроса. Да и название никудышное. Представляю, сколько сообщений было бы в ней ))
Может не стоит эту удалять? - возможно ссылки будут на конкретные сообщения. А вот новую создать действительно нужно.
 
Господа, идея разбирать мою программу и задачу, которая стоит перед программистом, а потом приходить к собственным выводам о том, что я не понимаю ни ее структуры ни принципа работы того, что создано и работает, принадлежит не мне. Я в теме задал довольно конкретный вопрос. Очевидно, что ответа на него пока не прозвучало ввиду нестандартности моей потребности. Да, я прекрасно знаю, что в программировании всегда есть альтернативы и за незнанием решения для поставленого мною вопроса мне пытались предлагать не ответ на вопрос, а альтрнативные решения, смутно понимая принцип организации довольно сложного кода.
То, что я хочу я описал в первом сообщении темы. То, что Вы хотите - описать принципы работы и архитектуру моей программы, описать одним сообщением нельзя так же, как невозможно в одном сообщении объяснить архитектуру Виндоус или эксель. И это не повод считать объясняющих не понимающими ее или самим запутавшейся в ней.
Вот ссылка на видео, где я попытался просто показать интерфейс работы программы и даже не раскрыл сотой части ее работы. на это уже ушло час. Я рекомендую не лезть с советами о том, как мне писать и переписывать ПО, особенно если Вы не понимаете сути и принципы работы этого ПО.
У меня был конкретный вопрос и я хотел бы обсуждать конкретно его, а не то, зачем мне это понадобилось. И в итоге слушать, что это не нужно, потому что советчики не поняли для чего это нужно.
Изменено: Neufazendnik - 22.06.2018 22:01:22
Страницы: 1 2 След.
Наверх