| 
			
			 | 
		#1 | 
| 
			
			 Модератор 
		
			
	 | 
	
	
	
		
		
			
			
			ComExcelDocument_RU  по именнованной ячейки вывести номер ее строки.
			 
			
			Вопрос: В Excel файле есть куча именованных ячеек. 
		
		
		
		
		
		
		
	Может кто нибудь знает как написать метод для класса ComExcelDocument_RU, чтоб по названию ячейки выдавал номер строки?   к примеру назвать такой метод- CellName2RowNumнеобходимо использовать для этого кода X++: static void Job104(Args _args) { ComExcelDocument_RU doc = new ComExcelDocument_RU(); int i; ; doc.open("C:\\test.xls"); doc.insertValue("test", 100); i=ComExcelDocument_RU::CellName2RowNum("test"); // info(int2str(i)); doc.insertClearRow(i); doc.insertValue("test", 200); i=ComExcelDocument_RU::CellName2RowNum("test"); // info(int2str(i)); doc.visible(true); }  | 
| 
	
 | 
| 
			
			 | 
		#2 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			Смотрите в сторону коллекции Names у объектов Application, Workbook, Worksheet 
		
		
		
		
		
		
			Только, в общем случае, имя может ссылаться на несколько ячеек, так что однозначно назвать колонку или столбец не получится 
				__________________ 
		
		
		
		
	Axapta v.3.0 sp5 kr2  | 
| 
	
 | 
| 
			
			 | 
		#3 | 
| 
			
			 Модератор 
		
			
	 | 
	
	
	
		
		
		
		 
			
			вот к примеру метод возращающий область, его как то можно допилить чтоб  возвращал именно номер строки?  
		
		
		
		
		
		
		
	X++: public COM getFindRange(MSOfficeBookMark_RU bookMark, int _workSheet = 1) { COM comRange, comWorkSheet; COM comApplication; if (m_comDocument) { comWorkSheet = this.getWorkSheet(_workSheet); comApplication = m_comDocument.application(); comWorkSheet.activate(); if (comWorkSheet && comApplication) { comRange = comApplication.range(bookMark); } } return comRange; }  | 
| 
	
 | 
| 
			
			 | 
		#4 | 
| 
			
			 Участник 
		
			
	 | 
	
	|
| 
	
 | 
| 
			
			 | 
		#5 | 
| 
			
			 Модератор 
		
			
	 | 
	
	
	
		
		
		
		 
			
			спасибо, я как раз уже насчупал его.. comRange.Row(); 
		
		
		
		
		
		
		
	все оказывается просто  | 
| 
	
 | 
| 
			
			 | 
		#6 | 
| 
			
			 Модератор 
		
			
	 | 
	
	
	
		
		
			
			 
			
			Спасибо, вопрос закрыт. 
		
		
		
		
		
		
		
	по имени ячейки берем номер строки X++: public int getCellName_RowNum(MSOfficeBookMark_RU bookMark, int _workSheet = 1) { COM comRange, comWorkSheet; COM comApplication; if (m_comDocument) { comWorkSheet = this.getWorkSheet(_workSheet); comApplication = m_comDocument.application(); comWorkSheet.activate(); if (comWorkSheet && comApplication) { comRange = comApplication.range(bookMark); } } return comRange.Row(); } X++: public int getCellName_ColumnNum(MSOfficeBookMark_RU bookMark, int _workSheet = 1) { COM comRange, comWorkSheet; COM comApplication; if (m_comDocument) { comWorkSheet = this.getWorkSheet(_workSheet); comApplication = m_comDocument.application(); comWorkSheet.activate(); if (comWorkSheet && comApplication) { comRange = comApplication.range(bookMark); } } return comRange.Column(); } X++: static void Job104(Args _args) { ComExcelDocument_RU doc = new ComExcelDocument_RU(); ; doc.open("C:\\test.xls"); doc.insertValue("test", 100); info('Row='+int2str(doc.getCellName_RowNum('test')) + ' Col='+ int2str(doc.getCellName_ColumnNum('test')) ); doc.insertClearRow(2); doc.insertValue("test", 200); doc.visible(true); }  | 
| 
	
 | 
| 
			
			 | 
		#7 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			Если даже в самом коде явно присутствуют как минимум два ветвления, ведущие к тому, что comRange может оказаться неинициализированным, не говоря уже о том, что на листе книги Excel может отсутствовать указанная "закладка", то имеет смысл проверять перед возвратом строки/столбца, что comRange на что-то ссылается, иначе придется то и дело ловить ошибки времени выполнения "объект такой-то неинициализирован".
		 
		
		
		
		
		
		
		
		
			Последний раз редактировалось gl00mie; 09.10.2008 в 22:05.  | 
| 
	
 | 
| 
			
			 | 
		#8 | 
| 
			
			 Moderator 
		
			
	 | 
	
	
	
		
		
		
		 
			
			О, больная тема! О, любимая мозоль!  
		
		
		
		
		
		
		
	![]() Poleax, бросайте изучать ComExcelDocument_RU, начинайте изучать Excel! Тогда вы будете знать, что для вставки пустой строки перед ячейкой не надо узнавать ее номер, чтобы потом скормить его методу-обертке, вставляющему i-ю строку в таблицу. Если танцевать от comRange, а не от вездесущего текстового букмарка ("test"), который на каждом шаге переводится всё в тот же comRange (который почему-то приговорен быть локальным в методах этого класса), то пустая строка перед comRange вставляется так: Код: comRange.EntireRow().Insert() P.S. При желании можно сократить кол-во строк до одной, если воcпользоваться последними достижениями в этой области ![]() X++: comEarlyBindingImitation( comRange,'EntireRow()','Insert()');  | 
| 
	
 | 
| 
			
			 | 
		#9 | 
| 
			
			 Moderator 
		
			
	 | 
	
	
	
		
		
			
			
			офф-топ
			 
			
			Ну, вот как раз еще один поучительный пример под горячую руку. 
		
		
		
		
		
		
		
	Это код фирменного (со слоя dis) метода из класса ComExcelDocument_RU (DAX 3.0, SP4). Я добавил несколько своих комментариев (в исходном фирменном виде метод не содержит комментариев, а также самой последней строки кода): X++: void copyAndInsertRange(str _bookMark, int _workSheet = 1) { COM comRange, comRange1, comWorkSheet; int colNumber, colsNumber; int rowNumber, rowsNumber; ; if (! m_comDocument) throw error(strFmt("@DIS6401", this.getApplicationName())); comRange = this.findRange(_bookMark, _workSheet); if (! comRange) { return; } rowNumber = comRange.row(); comRange1 = comRange.rows(); rowsNumber = comRange1.count(); // вычитаем единицу... (продолжение см. ниже) rowNumber = rowNumber - 1; colNumber = comRange.column(); comRange1 = comRange.columns(); colsNumber = comRange1.count(); /* // этот фрагмент кода не нужен, // он даже вредит, если выбрать диапазон, начинающийся со строки A comRange.copy(); comRange1 = this.findRange(ComExcelDocument_RU::numToNameCell(colNumber, rowNumber), _workSheet); if (! comRange1) { return; } comRange1.select(); m_comApplication.cutCopyMode(false); */ comRange = comRange.entireRow(); comRange.insert(); // следующие арифметические упражнения - без комментариев... ррррр! // P.S. А впрочем все-таки скажу. // Если бы в начале метода исходный comRange = this.findRange(_bookMark, _workSheet) // был сохранен в отдельную переменную, например, comRange0, // то вместо следующего ужасающего comRange = this.findRange(... достаточно было бы простого // comRange = comRange0 - поскольку при вставке строк перед Range его адрес автоматически переопределяется! comRange = this.findRange(ComExcelDocument_RU::numToNameCell(colNumber, rowNumber + rowsNumber + 1) + ":" + ComExcelDocument_RU::numToNameCell(colNumber + colsNumber - 1, rowNumber + 2*rowsNumber), _workSheet); if (! comRange) { return; } comRange.copy(); // ...чтобы потом вернуть эту вычтенную ранее единицу обратно (rowNumber + 1) :) comRange1 = this.findRange(ComExcelDocument_RU::numToNameCell(colNumber, rowNumber + 1), _workSheet); comRange1.select(); comWorkSheet = this.getWorkSheet(_workSheet); if (comWorkSheet) { comWorkSheet.paste(); } // а вот здесь этот оператор не помешает (при данном подходе) m_comApplication.cutCopyMode(false); } X++: void copyAndInsertRangeNew(str _bookMark, int _workSheet = 1) { COM comRange, comRange1; int rowsNumber; ; if (! m_comDocument) throw error(strFmt("@DIS6401", this.getApplicationName())); comRange = this.findRange(_bookMark, _workSheet); if (! comRange) { return; } rowsNumber = any2int(COM::createFromObject( comRange.Rows() ).Count()); COM::createFromObject(comRange.EntireRow()).Insert(); comRange1 = comRange.Offset(-rowsNumber); comRange.Copy(comRange1); } X++: void copyAndInsertRangeNew2(COM _comRange) { COM comRange1; int rowsNumber; ; rowsNumber = any2int(COM::createFromObject( _comRange.Rows() ).Count()); COM::createFromObject(_comRange.EntireRow()).Insert(); comRange1 = _comRange.Offset(-rowsNumber); _comRange.Copy(comRange1); } И в качестве постскриптума и для большей ясности - код VBA, который делает ту же работу, что и вышеприведенные методы X++: Код:  
Sub Macro1()
    Dim rng As Range
    Set rng = Worksheets(1).Range("B2:C4")
    
    rng.EntireRow.Insert
    rng.Copy rng.Offset(-rng.Rows.Count)
End Sub | 
| 
	
 | 
|
| За это сообщение автора поблагодарили: blokva (3), Poleax (2). | |
| 
			
			 | 
		#10 | 
| 
			
			 Модератор 
		
			
	 | 
	
	
	
		
		
		
		 
			
			Хорошо Gustav интересный код. Обязательно пригодится и использую.  
		
		
		
		
		
		
		
	Только у меня, еще немного другой вопрос. Как сделать чтоб передали методу параметры (str _bookMark, int _workSheet = 1) и для _BookMark скопировать всю эту область и вставить ниже, под копируемой областью. (с полным форматированием, и если ячейка именованная пользователем, то именованную ячейку перенести вниз.) ? А содержимое _bookMark оставить как есть.. но уже без имени ячейки. Т.е. копируем вставляем не всю строку, а только ту область которую указали.  | 
| 
	
 | 
| 
			
			 | 
		#11 | 
| 
			
			 Moderator 
		
			
	 | 
	
	
	
		
		
		
		 
			
			Т.е., как я понял, всё происходит так же, как и в методе copyAndInsertRange, только перед "букмарком" вставляются не полные строки, а диапазон с таким же размером, как у исходного "букмарка".  
		
		
		
		
		
		
		
	На VBA это выглядит так (отличие в одной строке): Код:  
Sub Macro2()
    Dim rng As Range
    Set rng = Range("B2:C4")
    
    rng.Insert xlShiftDown 'где константа xlShiftDown = -4121
    rng.Copy rng.Offset(-rng.Rows.Count)
End SubX++: // с COM::createFromObject(_comRange.EntireRow()).Insert(); // на _comRange.Insert( #xlShiftDown ); // и выше добавить: #define.xlShiftDown(-4121)  | 
| 
	
 | 
| 
			
			 | 
		#12 | 
| 
			
			 Модератор 
		
			
	 | 
	
	
	
		
		
		
		 
			
			Gustav Спасибо, а что за значение такое #define.xlShiftDown(-4121)?
		 
		
		
		
		
		
		
		
	 | 
| 
	
 | 
| 
			
			 | 
		#13 | 
| 
			
			 Модератор 
		
			
	 | 
	
	
	
		
		
			
			 
			
			Вопрос немного усложнился.  
		
		
		
		
		
		
		
	  Объединены ячейки 3 шт. Общей ячейке задано имя 'test'. при использовании X++: void copyAndInsertBlock(str _bookMark, int _workSheet = 1) { #define.xlShiftDown(-4121) COM comRange, comRange1; int rowsNumber; ; if (! m_comDocument) throw error(strFmt("@DIS6401", this.getApplicationName())); comRange = this.findRange(_bookMark, _workSheet); if (! comRange) { return; } rowsNumber = any2int(COM::createFromObject( comRange.Rows() ).Count()); comRange.Insert( #xlShiftDown ); // и выше добавить: #define.xlShiftDown(-4121) comRange1 = comRange.Offset(-rowsNumber); comRange.Copy(comRange1); } ![]() Как сделать так чтоб можно было копировать и дублировать именованную ячейку без потери объединения?  | 
| 
	
 | 
| 
			
			 | 
		#14 | 
| 
			
			 Moderator 
		
			
	 | 
	
	
	
		
		
		
		  ну, если хелп по Excel на своем компе совсем лениво открывать, то хотя бы здесь посмотрите: http://msdn.microsoft.com/en-us/library/bb178850.aspx Цитата: 
	
		
			Сообщение от Poleax
			 
 
			при вставки объединенной ячейки появляется сообщение "Данная операция приведет к отмене объединения ячеек" т.е. ниже в файле Excel есть объединенные ячейки. Объединение с них снимается и в итоге данные передаваемые в именованную ячейку вставляются не в 3-ную объединенную, а самую первую. А две остальных даже не копируются вниз.  
		
	![]() Как сделать так чтоб можно было копировать и дублировать именованную ячейку без потери объединения? Если всё-таки хочется решать задачу именно в вашей постановке, то видится такой извратный вариант - сдвигать все оставшиеся ячейки шаблона ниже места вставки вправо (как дверь шкафа-купе), потом делать копирование, потом возвращать "дверь" обратно. Стоит ли игра таких свеч?  | 
| 
	
 | 
| 
			
			 | 
		#15 | 
| 
			
			 Модератор 
		
			
	 | 
	
	
	
		
		
		
		 Цитата: 
	
		
			Сообщение от Gustav
			 
 
			  ну, если хелп по Excel на своем компе совсем лениво открывать, то хотя бы здесь посмотрите: http://msdn.microsoft.com/en-us/library/bb178850.aspx Цитата: 
	
		
			Сообщение от Gustav
			
			 
Самый простой вариант решения проблемы - вернуться к вставке полных строк. Еще вариант - отказаться от объединенных ячеек. В подавляющем большинстве практических случаев они могут быть безболезненно для отображения заменены центрированием по выделению (Формат \ Ячейки \ Выравнивание \ По горизонтали \ По центру выделения).  
		
	Если всё-таки хочется решать задачу именно в вашей постановке, то видится такой извратный вариант - сдвигать все оставшиеся ячейки шаблона ниже места вставки вправо (как дверь шкафа-купе), потом делать копирование, потом возвращать "дверь" обратно. Стоит ли игра таких свеч?   со вставкой строки сразу отпадает. В отчете ячейки слишком мелкие и они объединены в "по больше". Как у именованной ячейки узнать с кем она объединена? (сколько ячеек в право и сколько вниз.) А потом после вставке основной первой именованной все остальные продублировать также и после всего их объединить?  
		 | 
| 
	
 | 
| 
			
			 | 
		#16 | 
| 
			
			 Moderator 
		
			
	 | 
	
	
	
		
		
		
		 
			
			Ну-ну! Идём в Excel в редактор кода VBA по Alt+F11, пишем в окне отладки: Range("A1").Insert  
		
		
		
			Щелкаем мышкой в середине слова Insert и жмем F1 - появляется топик хелпа Читая топик, видим интересующую нас константу xlShiftDown. Копируем эту строку в окно отладки и ставим перед ней восклицательный знак (сократитель команды Print), после чего нажимаем Enter Ну это-то конечно. Типа "пусть работает железная пила" ![]() См. MergeArea - cвойство объекта Range. Возвращает тоже Range. Например, если объединены ячейки A1:C2, то Range("A1").MergeArea.Address вернет $A$1:$C$2. Еще есть булевское свойство MergeCells объекта Range - возвращает True, если ячейка входит в объединение.  | 
| 
	
 | 
| 
			
			 | 
		#17 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			Еще можно воспользоваться Object Browser'ом (кнопка F2 в VBA). В разделе Globals перечислены все константы и их значения
		 
		
		
		
		
		
		
			
				__________________ 
		
		
		
		
	Axapta v.3.0 sp5 kr2  | 
| 
	
 | 
| 
			
			 | 
		#18 | 
| 
			
			 Пенсионер 
		
			
	 | 
	
	
	
		
		
		
		 Цитата: 
	
		
			Сообщение от Poleax
			 
 
			Вопрос немного усложнился.  
		
	  Объединены ячейки 3 шт. Общей ячейке задано имя 'test'. при использовании ..... при вставки объединенной ячейки появляется сообщение "Данная операция приведет к отмене объединения ячеек" т.е. ниже в файле Excel есть объединенные ячейки. Объединение с них снимается и в итоге данные передаваемые в именованную ячейку вставляются не в 3-ную объединенную, а самую первую. А две остальных даже не копируются вниз. ![]() Как сделать так чтоб можно было копировать и дублировать именованную ячейку без потери объединения? Это что же вы в файле перекрываете именованные объединенные диапазоны? Очень странно это, зачем тогда объединять и именовать? Если Вы хотите то что написали в первом посту, то Gustav Вам подсказал как это делать, если Вам требуется перекрывать объединенные дипазоны, то это совсем другая задача, А может Вы просто опишите Вашу задачу не кусками, а целиком и Вам возможно подскажут правильное решение. 
				__________________ 
		
		
		
		
	  Законы природы еще никто не отменял!А еще у меня растет 2 внучки!!! Кому интересно подробности тут: http://www.baby-shine.com/  | 
| 
	
 | 
|
| За это сообщение автора поблагодарили: aidsua (1). | |
| 
			
			 | 
		#19 | 
| 
			
			 Moderator 
		
			
	 | 
	
	
	
		
		
		
		 Цитата: 
	
Код: Sub Macro1()
    Range("A6:C12").Insert xlShiftToRight 'xlShiftToRight = -4161
End Sub
Sub Macro2()
    Dim rng As Range
    Set rng = Range("B3")
    
    rng.Insert xlShiftDown 'xlShiftDown = -4121
    rng.Copy rng.Offset(-rng.Rows.Count)
End Sub
Sub Macro3()
    Range("A6:C12").Delete xlShiftToLeft 'xlShiftToLeft = -4159
End SubПосле отработки Macro1 - сдвинули "дверь" вправо: После отработки Macro2 - выполнили размножение (объединенная голубая ячейка не мешает): После отработки Macro3 - вернули "дверь" назад:  | 
| 
	
 | 
|
| За это сообщение автора поблагодарили: aidsua (1). | |
| 
			
			 | 
		#20 | 
| 
			
			 Модератор 
		
			
	 | 
	
	
	
		
		
		
		 
			
			blokva   
		
		
		
		
		
		
		
	Задача: в Excel файле есть ячейка с именем. ("TEST") оказывается она ре одинарная а состоит из нескольких, объединенных. Надо продублировать ячейку вниз целиком и полностью, с сохранением форматирования и объединений. Каждый раз при дублировании ячейки вниз в нее вставляю через цикл значение. На данный момент вставка происходит, все хорошо, кроме одного. Если ячейка состояла из нескольких то при вставке объединение теряется. Gustav Спасибо за мастер-класс по Help(у). Как мне в аксапте вытянуть этот диапазон Range("A1").MergeArea.Address чтоб потом по нему megre сделать. X++:     COM         comRange, comRange1, comR;
   comR=comRange.MergeArea();
   comR.merge(); //че то не то.. | 
| 
	
 |