Excel скопировать ячейку программно

Вырезание, перемещение, копирование и вставка ячеек (диапазонов) в VBA Excel. Методы Cut, Copy и PasteSpecial объекта Range, метод Paste объекта Worksheet.

Метод Range.Cut

Range.Cut – это метод, который вырезает объект Range (диапазон ячеек) в буфер обмена или перемещает его в указанное место на рабочем листе.

Синтаксис

Параметры

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

Для вставки на рабочий лист диапазона ячеек, вырезанного в буфер обмена методом Range.Cut, следует использовать метод Worksheet.Paste.

Метод Range.Copy

Range.Copy – это метод, который копирует объект Range (диапазон ячеек) в буфер обмена или в указанное место на рабочем листе.

Синтаксис

Параметры

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

Метод Worksheet.Paste

Worksheet.Paste – это метод, который вставляет содержимое буфера обмена на рабочий лист.

Синтаксис

Worksheet.Paste (Destination, Link)

Метод Worksheet.Paste работает как с диапазонами ячеек, вырезанными в буфер обмена методом Range.Cut, так и скопированными в буфер обмена методом Range.Copy.

Параметры

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

В выражении с методом Worksheet.Paste можно указать только один из параметров: или Destination, или Link.

Для вставки из буфера обмена отдельных компонентов скопированных ячеек (значения, форматы, примечания и т.д.), а также для проведения транспонирования и вычислений, используйте метод Range.PasteSpecial (специальная вставка).

Примеры

Вырезание и вставка диапазона одной строкой (перемещение):

Range(«A1:C3»).Cut Range(«E1»)

Вырезание ячеек в буфер обмена и вставка методом ActiveSheet.Paste:

Range(«A1:C3»).Cut

ActiveSheet.Paste Range(«E1»)

Копирование и вставка диапазона одной строкой:

Range(«A18:C20»).Copy Range(«E18»)

Копирование ячеек в буфер обмена и вставка методом ActiveSheet.Paste:

Range(«A18:C20»).Copy

ActiveSheet.Paste Range(«E18»)

Копирование одной ячейки и вставка ее данных во все ячейки заданного диапазона:

Range(«A1»).Copy Range(«B1:D10»)


На чтение 3 мин. Просмотров 51.6k.

Итог: Изучите 3 различных способа копирования и вставки ячеек или диапазонов в Excel с помощью макросов VBA. Это серия из трех частей, также вы сможете скачать файл, содержащий код.

Уровень мастерства: Начинающий

Копировать и вставить: наиболее распространенное действие Excel

Копирование и вставка, вероятно, является одним из самых
распространенных действий в Excel. Это также одна из самых распространенных
задач, которые мы автоматизируем при написании макросов.

Есть несколько различных способов выполнить эту задачу, и устройство записи макросов не всегда дает вам наиболее эффективный код VBA.

В следующих трех видео я объясняю:

  • Самый эффективный метод для простого копирования
    и вставки в VBA.
  • Самый простой способ вставить значения.
  • Как использовать метод PasteSpecial для других
    типов вставок.

Видео № 1: Простой метод «Копировать-вставить»

Видео лучше всего просматривать в полноэкранном HD.

Sub Примеры_копирования_диапазона()
'Используйте метод Range.Copy для простого копирования / вставки

    'Метод Range.Copy - копирование и вставка с 1 строкой
    Range("A1").Copy Range("C1")
    Range("A1:A3").Copy Range("D1:D3")
    Range("A1:A3").Copy Range("D1")
    
    'Range.Copy с одного листа на другой
    Worksheets("Лист1").Range("A1").Copy Worksheets("Лист2").Range("A1")
    
    'Range.Copy с одного файла (на другой
    Workbooks("План.xlsx").Worksheets("Лист1").Range("A1").Copy _
        Workbooks("Факт.xlsx").Worksheets("Лист1").Range("A1")

End Sub

Видео № 2: Простой способ вставить значения

Sub Копируем_только_значения()
'Установите значения ячеек равными другим, чтобы вставить значения

'Устанавливает равенство одного диапазона другому
    Range("C1").Value = Range("A1").Value
    Range("D1:D3").Value = Range("A1:A3").Value
     
'Равенство значений между листами
    Worksheets("Лист1").Range("A1").Value = Worksheets("Лист2").Range("A1").Value
     
'Равенство значений между книгами
    Workbooks("Факт.xlsx").Worksheets("Лист1").Range("A1").Value = _
        Workbooks("План.xlsx").Worksheets("Лист1").Range("A1").Value
        
End Sub

Видео № 3: Метод PasteSpecial

Sub Копируем_с_помощью_специальной_вставки()
'Используйте метод Range.PasteSpecial для выбора типа вставки

 'Копируем и вставляем через СпецВставку
Range("A1").Copy
Range("A5").PasteSpecial Paste:=xlPasteFormats

'Используем спецвставку между листами
Worksheets("Лист1").Range("A2").Copy
Worksheets("Лист2").Range("A2").PasteSpecial Paste:=xlPasteFormulas

'Используем спецвставку между файлами
Workbooks("План.xlsx").Worksheets("Лист1").Range("A3").Copy
Workbooks("Факт.xlsx").Worksheets("Лист1").Range("A1").PasteSpecial Paste:=xlPasteFormats

'Убираем "бегающих муравьёв" после копирования (очищаем буфер обмена)
Application.CutCopyMode = False    
   
End Sub

Вставить данные ниже последней заполненной строки

Один из самых распространенных вопросов, которые я получаю о копировании и вставке с помощью VBA: «Как мне вставить данные в конец таблицы? «

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

Переходите по ссылке, чтобы научиться 3 способам поиска последней заполненной ячейки

How to copy and paste data using a Macro in Excel. I’ll show you multiple ways to do this, including across worksheets and workbooks.

Sections:

Simple Copy/Paste

Copy Entire Range

Copy between Worksheets

Copy between Workbooks

Notes

Simple Copy/Paste

Range("A1").Copy Range("B1")

This copies cell A1 to cell B1.

Range(«A1»).Copy is the part that copies the cell.

Range(«B1») is the cell where the data will be copied.

This is a simple one line piece of code and it’s very easy to use.

Notice that there is a space between these two parts of the code.

Copy Entire Range

Range("A1:A5").Copy Range("B1:B5")

Range(«A1:A5»).Copy is the part that copies the range.

Range(«B1:B5») is the range where the data will be copied.

You can also write it like this:

Range("A1:A5").Copy Range("B1")

Notice that the range to where you will copy the data has only a reference to cell B1.

You only have to reference the very first cell to which the range will be copied and the entire range will copy in the cells below there.

NOTE: if you do it like this, you may end up overwriting data and Excel will not give you a warning about this; the data will simply be filled down as far as it needs to go to copy the first range.

Copy between Worksheets

Sheets("Sheet1").Range("A1").Copy Sheets("Sheet2").Range("B1")

This follows the same pattern as the above examples except that we need to tell the macro from which sheet we want to get the data and to which sheet we want to copy the data.

Sheets(«Sheet1»). is placed in front of the first range and that means to get the data from Sheet1, which is the name of a worksheet in the workbook.

Sheets(«Sheet2»). is placed in front of the range to which we want to copy the data and Sheet2 is the name of the worksheet where the data will be copied.

Copy between Workbooks

Workbooks("Copy and Paste Data using Macro VBA in Excel.xlsm").Sheets("Sheet1").Range("A1").Copy Workbooks("Copy and Paste Data using Macro VBA in Excel.xlsm").Sheets("Sheet3").Range("A1")

Here, we follow the above examples and, this time, add a reference to the workbooks from which we want to get the data and to which we want to place the data.

Workbooks(«Copy and Paste Data using Macro VBA in Excel.xlsm»). is the code that says in which workbook we want to place the data. Copy and Paste Data using Macro VBA in Excel.xlsm is the name of the workbook. In this example I used this for both parts, the workbook from which the data comes and where it goes. This allows you to run this macro within a single workbook and still show you how it works. In a real-world example, the first part contains the name of the workbook where you get the data from and the second contains the name of the workbook where you want to place the data.

Read this tutorial to copy values from another workbook, even if it’s closed.

Notes

All examples in the attached workbook have been commented out. Simply remove the single quote from the line of code you want to test and then run the macro.

cf5e0ebf6d62c9ec73df03c55f727e77.jpg

Download the attached file to get these examples in Excel.

Similar Content on TeachExcel

Activate or Navigate to a Worksheet using Macros VBA in Excel

Tutorial: Make a particular worksheet visible using a macro in Excel.
This is called activating a wo…

Get the Name of a Worksheet in Macros VBA in Excel

Tutorial: How to get the name of a worksheet in Excel using VBA and Macros and also how to store tha…

Get the Last Row using VBA in Excel

Tutorial:
(file used in the video above)
How to find the last row of data using a Macro/VBA in Exce…

Remove Dashed Lines from Copy Paste VBA in Excel

Tutorial: How to remove the flashing dashes from a copy/paste range using VBA in Excel; this removes…

Copy one range and paste in another range

Tutorial: Below is a macro, just copy and paste it into a module in your workbook and go from there…

Guide to Combine and Consolidate Data in Excel

Tutorial: Guide to combining and consolidating data in Excel. This includes consolidating data from …

Subscribe for Weekly Tutorials

BONUS: subscribe now to download our Top Tutorials Ebook!

2006 г.

Cells, Range, Rows и Columns

  • Как записать значения сразу в несколько ячеек?
  • Как определить область выделенных ячеек и ее границы?
  • Как записывать значения в ячейку (Value, Value2, Text, Formula)?
  • Что работает быстрее, запись в Range или Cells?
  • Что такое UsedRange? Как найти последнюю используемую ячейку? Что такое SpecialCells? Что такое CurrentRegion?
  • Как получить адрес ячейки?
  • Нужно ли выделять ячейку/область для того чтобы вносить в нее данные?
  • В чем отличие Range.Activate от Range.Select?
  • Как установить свойству ячейки NumberFormat «общий» формат, текстовый формат, формат даты, числа, валюты?
  • Передаю в ячейку 385.00, а показывает 385. Почему?
  • При записи в ячейку чисел как текста, целые числа автоматический преобразуются в численный формат, а вещественные нет. Вследствие чего возникает ошибка «число сохранено как текст».
  • Делаю экспорт в Excel, допустим, текст «000069987», а он выводит в ячейку 69987, т.е. удаляет лидирующие нули. Как мне сделать, чтобы в ячейку выводилось 000069987?
  • Как очистить область ячеек? Как определить что ячейка Excel пустая?
  • Как задать имя области ячеек? Как обратиться к ячейке по имени? Как определить, что такое имя существует на листе? Как задать имя области ячеек?
  • Как объединить ячейки? Как узнать, что ячейка входит в объединенную область и определить границы этой области?
  • Как записывать данные из вариантного массива в Excel?
  • Как прочесть данные из области ячеек в массив?
  • Почему при выгрузке данных в Excel не могу записать строк больше 65536?
  • Как писать в ячейки нескольких листов сразу?
  • Как изменить цвет фона и шрифта ячейки?
  • Как изменить атрибуты шрифта части текста в ячейке (цвет, размер, имя)?
  • Как узнать позицию курсора в редактируемой по F2 ячейке или в строке формул и дописать в нее текст?
  • Как изменить выравнивание/угол наклона текста, отступы в ячейке?
  • Как задать границы для области ячеек (Borders)?
  • Как скопировать форматы и формулы из строки в нижележащую область (AutoFill)?
  • Как скопировать область ячеек с сохранением всех форматов? Как скопировать только значения ячейки?
  • Как скопировать область, чтоб сохранились размеры строк/столбцов?
  • Как сделать автоперенос строк в ячейке?
  • Как вставить несколько строк/столбцов? Как удалить несколько строк/столбцов? Как прятать/показывать строки и столбцы? Как программно изменить высоту строки или ширину столбца?
  • Как подогнать высоту или ширину ячеек для отображения всего текста?
  • Как сделать автоподбор высоты строк для объединенных ячеек?
  • Как программно «заморозить» строки/столбцы?
  • Как добавить примечание к ячейке? Как удалить примечание? Как изменить атрибуты шрифта примечания?
  • Как добавить URL? Как сделать гиперссылку для рисунка?
  • Как отсортировать область ячеек?
  • Как сделать поиск значений в области ячеек или по всему листу?
  • Как, имея ссылку на ячейку, узнать имя листа, которому она принадлежит? Узнать имя книги?
  • Полезные ссылки

Объект Cells предназначен для доступа к ячейкам в стиле R1C1 к одной ячейке. Range — в стиле A1 к области (коллекции) ячеек. Удобство объекта Range в том, что можно, при использовании оператор with, обращаться к нескольким свойствам и методам. Объект Rows возвращает коллекцию строк и Columns — коллекцию столбцов объекта Range (вместо этих свойств можно использовать свойства EntireRow и EntireColumn).

Range Collection

Cells Property

Rows Property

Columns Property

Excel Range Object

Как записать значения сразу в несколько ячеек?

Для записи в несколько (область) ячеек используется объект Range (ExcelRange). Пример, как можно получить объект Range для области ячеек.

Delphi:

oRng: ExcelRange;
...
    ASheet := (XL.ActiveWorkbook.ActiveSheet as _Worksheet);
    oRng := ASheet.Range['A1:B5', EmptyParam];
    oRng := ASheet.Range['A1', 'B5'];
    oRng := ASheet.Range[ASheet.Cells.Item[1, 1], ASheet.Cells.Item[5, 2]];
    oRng.Formula := 123.45;


// обращение к объекту Rows
    oRng := ASheet.Range['3:7', EmptyParam].Rows;
    oRng := ASheet.Range['A3:A7', EmptyParam].EntireRow;

// обращение к объекту Columns
    oRng := ASheet.Range['B:E', EmptyParam].Columns;
    oRng := ASheet.Range['B1:E1', EmptyParam].EntireColumn;

Заметьте, что при обращении к свойству Range и Cells объекта Range, адресация будет уже работать относительно области, указанной в объекте Range. Например, нижеприведенный код будет указывать не на ячейку «A1», как сразу можно подумать, а на «C2»:

ASheet.Range['C2:F20', EmptyParam].Range['A1', EmptyParam];

А вот такой код вернет ячейку с адресом «D3»:

ASheet.Range['C2:F20', EmptyParam].Range['B2', EmptyParam];

EntireRow Property

EntireColumn Property

How to: Refer to Worksheet Ranges in Code

Как определить область выделенных ячеек и ее границы?

Чтобы получить область (или области) выделенных ячеек, нужно получить объект Range из свойства Selection объекта Excel.Application и обратиться к свойству Range.Areas.

Delphi:

    try
      with XL.Selection[lcid] as ExcelRange do

        for i := 1 to Areas.Count do
          with Areas[i] do

            ShowMessageFmt('R%dC%d:R%dC%d',
              [Row, Column, Row + Rows.Count - 1, Column + Columns.Count - 1]);
    except
      // Selection - это не Range!
    end;

Areas Property

Selection Property

Как записывать значения в ячейку (Value, Value2, Text, Formula)?

Начиная с версии Excel XP (10.0), свойство Value имеет параметр. Отличие Value2 от Value в том, что Value2 не поддерживает «форматирования на лету» для типов Currency, Double и Date. Свойство Text (только чтение для Range) возвращает текст в ячейке. Свойство Formula выполняет те же функции, что и Value, с поддержкой «форматирования на лету», а также позволяет записывать в ячейку формулы со ссылками в стиле A1 (в идеале английские, но что на практике, смотрите здесь). Для стиля R1C1 используется свойство FormulaR1C1.

Для записи локализованных («русских») форматов данных и формул используются свойства с окончанием Local, например FormulaLocal.

Delphi:

Range['A1', EmptyParam].Value2 := 'Любой текст';
Range['A2', EmptyParam].Value[xlRangeValueDefault] := 123.45;
Range['A3', EmptyParam].Formula := Date;

// Будьте внимательны - в английских формулах разделитель аргументов
// только символ "," (запятая), а не ";", как в русских формулах!
Range['A4', EmptyParam].Formula := '=sum(A2:A3)';

C#:

// согласитесь, что немного неудобно писать так
oSheet.get_Range("A6", Type.Missing).set_Value(
  Excel.XlRangeValueDataType.xlRangeValueDefault, 123.45);
// или
oSheet.get_Range("A7", Type.Missing).set_Value(Type.Missing, 123.45);
// гораздо удобнее
oSheet.get_Range("A6", Type.Missing).Value2 = 123.45;
// или
oSheet.get_Range("A6", Type.Missing).Formula = 123.45;

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

Внимание! При записи в свойство Formula, если это не формула, следите, чтобы текст не начинался с символов «=», «+», «-«, «*», «/». Или просто к тексту прибавляйте в начало знак апострофа (код символа 39):

Delphi:

Range['A1', EmptyParam].Formula := #39'Любой текст';
Range['A1', EmptyParam].Formula := #39 + MyStringVar;

По волнам интеграции… III

Value Property

Value2 Property

Formula Property

Text Property

Что работает быстрее, запись в Range или Cells?

Запись в Range работает быстрее, но не существенно (смотрите в Demo-проекте пример «Как сделать, чтобы Excel работал быстрее?»). Это связано с тем, что в Excel TLB свойство Cells.Item[R, C] имеет тип OleVariant и, как следствие, позднее связывание. В C# между Range и Cells нет никакой разницы.

Для перевода из координат R1C1 в A1 удобно пользоваться «самодельными» функциями, например:

Delphi:

function xlRCtoA1(const ARow, ACol: Integer;
  RowAbsolute: Boolean = False;
  ColAbsolute: Boolean = False): String;

const
  A1 = Ord('A') - 1;  // номер "A" минус 1 (65 - 1 = 64)
  AZ = Ord('Z') - A1; // кол-во букв в англ. алфавите (90 - 64 = 26)

var
  t, m: Integer;
  S: String[9]; // чтобы экономить память IV=256 последний столбец 
begin
  // номер колонки
  t := ACol div AZ; // целая часть

  m := (ACol mod AZ); // остаток?
  if m = 0 then Dec(t);
  if t > 0 then S := Char(A1 + t) else S := '';
  if m = 0 then t := AZ else t := m;
  S := S + Char(A1 + t);
  // весь адрес

  if ColAbsolute then S := '$' + S;
  if RowAbsolute then S := S + '$';
  S := S + IntToStr(ARow);
  Result := S;

end;

Вот еще примеры

Что такое UsedRange? Как найти последнюю используемую ячейку? Что такое SpecialCells? Что такое CurrentRegion?

UsedRange — прямоугольная область, включающая все заполненные ячейки и незаполненные, в промежутках между заполненными ячейками, на листе. Координаты области не обязательно начинаются в ячейке A1. Также для определения координат различных ячеек можно использовать объект SpecialCells, например, с параметром xlCellTypeLastCell для нахождения последней (крайней справа снизу) используемой ячейки. CurrentRegion возвращает область вокруг ячейки, выделенную пустыми (незаполненными) ячейками. End — находит последнюю ячейку в строке или столбце перед первой попавшейся пустой ячейкой, или первую заполненную, если вызывать метод End для пустой ячейки.

Delphi:

R: ExcelRange;
...
// вся используемая область ячеек (прямоугольная)
R := ASheet.UsedRange[lcid];

// получить последнюю (правую нижнюю) ячейку используемой области
R := ASheet.Range['A1', EmptyParam].SpecialCells(xlCellTypeLastCell, EmptyParam);

// получить все непустые ячейки вокруг ячейки "A5" (удобно для обнаружения таблиц
// на листе)

R := ASheet.Range['A5', EmptyParam].CurrentRegion;

// Найти последнюю непустую ячейку в столбце, если "A9" - непустая ячейка.
// Или первую непустую, если "A9" - пустая ячейка.
R := ASheet.Range['A9', EmptyParam].End_[xlDown];

UsedRange Property

SpecialCells Method

CurrentRegion Property

End Property

Как получить адрес ячейки?

Delphi:

R: ExcelRange;
...
    // абсолютные координаты в стиле A1

    R := ASheet.Range['A1', EmptyParam];
    R.Select;
    R.Formula := R.Address[True, True, xlA1, EmptyParam, EmptyParam];

    // относительные координаты в стиле A1
    R := ASheet.Range['A2', EmptyParam];
    R.Formula := R.Address[False, False, xlA1, EmptyParam, EmptyParam];

    // если указать RowAbsolute и ColumnAbsolute False,
    // то будет выдан адрес относительно активной ячейки
    R := ASheet.Range['A3', EmptyParam];
    R.Formula := R.Address[False, False, xlR1C1, EmptyParam, EmptyParam];

    // теперь получим абсолютный адрес

    R := ASheet.Range['A4', EmptyParam];
    R.Formula := R.Address[True, True, xlR1C1, EmptyParam, EmptyParam];

    // также координаты ячейки можно получить из свойств
    // Row и Column объекта Range
    R := ASheet.Range['A5', EmptyParam];
    R.Formula := Format('Строка %d, Колонка %d', [R.Row, R.Column]);

Address Property

Row Property

Column Property

Нужно ли выделять ячейку/область для того, чтобы вносить в нее данные?

Не нужно. Достаточно указать адрес области ячеек в объекте Range для выбранного объекта Worksheet (и/или Workbook). Любой Select или Activate только замедлит работу вашей программы. Кроме того, метод Select возможно вызвать только на активном листе активной книги! Не используйте Select и Activate без необходимости.

Best Practices for Setting Range Properties

В чем отличие Range.Activate от Range.Select?

И метод Activate и Select делают одно и то же — выделяют (активируют) ячейку. Разница лишь в том, что метод Activate позволяет выбрать только одну ячейку на листе или сделать активной любую ячейку в области, выделенной методом Select. Метод Select позволяет выделять одну и более областей ячеек.

Select Method

Activate Method

Как установить свойству ячейки NumberFormat «общий» формат, текстовый формат, формат даты, числа, валюты?

Для правильной работы NumberFormat с английскими форматами не забудьте подключить модуль TrDispCall

Delphi:

// Установка текстового формата.
    // Записанное число как текст будет воспринят как текст,
    // если указать текстовый формат
    with ASheet.Range['A1', EmptyParam] do begin

      NumberFormat := '@';
      Value[xlRangeValueDefault] := '1234567890123456';
    end;
    // Записанное число как текст будет воспринят как число,
    // если указать общий формат
    with ASheet.Range['A1', EmptyParam] do begin

      NumberFormat := '';
      Value2 := '1234567890123456';
    end;
    // Записанное в ячейку число будет воспринято как число, но
    // с выравниванием влево как текст
    with ASheet.Range['A1', EmptyParam] do begin

      NumberFormat := '@';
      Value2 := Now();
    end;
    // Для установки "общего" формата достаточно записать
    // в свойство NumberFormat пустую строку
    with ASheet.Range['A1', EmptyParam] do begin

      NumberFormat := '';
    end;
    // Для установки формата даты запишем в NumberFormat
    // формат "короткой" даты.
    with ASheet.Range['A1', EmptyParam] do begin

      NumberFormat := ShortDateFormat; // SysUtils
    end;
    // Установим формат целых чисел с разделителем тысяч
    with ASheet.Range['A1', EmptyParam] do begin

      NumberFormat := '#,##0';
    end;
    // Установим формат float чисел с разделителем тысяч и
    // двумя знаками после запятой
    with ASheet.Range['A1', EmptyParam] do begin

      NumberFormat := '#,##0.00';
    end;

NumberFormat

Передаю в ячейку 385.00, а показывает 385. Почему?

Потому что в ячейке установлен «общий» формат (general), который отсекает незначащие цифры. В данном примере всегда будут указываться 2 цифры после запятой:

Delphi:

ASheet.Range['A1', EmptyParam].NumberFormat := '0.00';
ASheet.Range['A1', EmptyParam].Value2 := 385; // будет отображено "385.00"

При записи в ячейку чисел как текста, целые числа автоматический преобразуются в численный формат, а вещественные нет. Вследствие чего возникает ошибка «число сохранено как текст».

Лучше числа не записывать в ячейку как текст и не надеяться, что Excel всегда сможет «на лету» преобразовать текст верно. Вы никогда не можете быть уверенными, какие локальные установки формата чисел будут установлены на компьютере пользователя. Всегда перед записью переводите записываемые числа из текста в число (Float или Integer) в своей программе.

Делаю экспорт в Excel, допустим, текст «000069987», а он выводит в ячейку 69987, т.е. удаляет лидирующие нули. Как мне сделать, чтобы в ячейку выводилось 000069987?

При записи текста, содержащего одни цифры, Excel пытается его преобразовать в число. Чтобы избажать такой «помощи» со стороны Excel’я, перед записью в ячейку установите в свойство NumberFormat текстовый формат или добавьте перед текстом символ апострофа «‘» (код символа 39).

Delphi:

    S := '000069987';
    // установим текстовый формат перед записью в ячейку
    with ASheet.Range['A1', EmptyParam] do begin

      NumberFormat := '@';
      Formula := S;
    end;
    // или добавим перед текстом апостроф - результат тот же и даже быстрее работает
    // так как не приходится изменять свойство NumberFormat
    ASheet.Range['A2', EmptyParam].Formula := #39 + S;

Как очистить область ячеек? Как определить что ячейка Excel пустая?

Delphi:

    ASheet.Range['A1', EmptyParam].Formula := 123.45;
    ASheet.Range['A2', EmptyParam].Formula := 0;


// проверяем
    ASheet.Range['B1', EmptyParam].Formula := VarIsClear(ASheet.Range['A1', EmptyParam].Value2);
    ASheet.Range['B2', EmptyParam].Formula := VarIsClear(ASheet.Range['A2', EmptyParam].Value2);
    ASheet.Range['B3', EmptyParam].Formula := VarIsClear(ASheet.Range['A3', EmptyParam].Value2);

// Записали в ячейку информацию и проверяем, что вернет нам функция VarIsClear

// Запишем в A3 пустой текст, а в A1 очистим форматы
    ASheet.Range['A1', EmptyParam].ClearFormats;
    ASheet.Range['A3', EmptyParam].Formula := '';

// проверим
    ASheet.Range['B1', EmptyParam].Formula := VarIsEmpty(ASheet.Range['A1', EmptyParam].Value2);
    ASheet.Range['B2', EmptyParam].Formula := VarIsEmpty(ASheet.Range['A2', EmptyParam].Value2);
    ASheet.Range['B3', EmptyParam].Formula := VarIsEmpty(ASheet.Range['A3', EmptyParam].Value2);


// После записи пустой строки ячейка так и осталась "пустой"
// Очистим содержание всех ячеек и посмотрим, что получилось
    ASheet.UsedRange[lcid].ClearContents;
    ASheet.Range['B1', EmptyParam].Formula := VarIsEmpty(ASheet.Range['A1', EmptyParam].Value2);
    ASheet.Range['B2', EmptyParam].Formula := VarIsEmpty(ASheet.Range['A2', EmptyParam].Value2);
    ASheet.Range['B3', EmptyParam].Formula := VarIsEmpty(ASheet.Range['A3', EmptyParam].Value2);


// Видно, что теперь все ячейки "пустые" (нет данных).

Чтобы радикально очистить ячейки (данные, форматы, примечания и т.д.), можно вызвать метод Clear.

Clear Method

ClearContents Method

ClearFormats Method

Как задать имя области ячеек? Как обратиться к ячейке по имени? Как определить, что такое имя существует на листе? Как задать имя области ячеек?

Delphi:

// создадим функцию для проверки наличия именованной области ячеек на листе
function RangeNameExists(ASheet: ExcelWorksheet; const ARangeName: String): Boolean;
var
  i: Integer;
  S: ExcelWorksheet;
  WB: ExcelWorkbook;

begin
  Result := False;
  if not Assigned(ASheet) then Exit;
  WB := ASheet.Parent as ExcelWorkbook;
  for i := 1 to WB.Names.Count do begin

    if AnsiSameText(WB.Names.Item(i, EmptyParam, EmptyParam).Name_, ARangeName) then begin
      // имя нашли, а на нашем ли листе?
      S := WB.Names.Item(i, EmptyParam, EmptyParam).RefersToRange.Worksheet as ExcelWorksheet;
      Result := AnsiSameText(S.Name, ASheet.Name);
      if Result then Break;
    end;
  end;

end;

// присвоим имя "MyNamedRange" области "B2:D7"
    (ASheet.Parent as ExcelWorkbook).Names.Add(
      'MyNamedRange', // Name,

      ASheet.Range['B2:D7', EmptyParam], // RefersTo: OleVariant; стиль адресации A1
      True, // Visible: OleVariant;
      EmptyParam, // MacroType: OleVariant;
      EmptyParam, // ShortcutKey: OleVariant;

      EmptyParam, // Category: OleVariant;
      EmptyParam, // NameLocal: OleVariant;
      EmptyParam, // RefersToLocal: OleVariant;
      EmptyParam, // CategoryLocal: OleVariant;
      EmptyParam, // RefersToR1C1: OleVariant; // адрес в стиле R1C1

      EmptyParam // RefersToR1C1Local: OleVariant
    ); // : Name;

// теперь попробуем определить наличие именованной области и, если есть такая, 
// обведем область рамкой

    if RangeNameExists(ASheet, 'MyNamedRange')
      then ASheet.Range['MyNamedRange', EmptyParam].BorderAround(
        xlContinuous,
        xlThick,
        xlColorIndexAutomatic,
        EmptyParam
        );

Если вы зададите области имя, уже существующее в листе, то старое имя будет утеряно, т.е. получится перезапись имени. Присваивать имена области ячеек можно и неактивному листу. Задавать адрес ячейки можно и как текст (не обязательно ссылку на объект Range), а также можно в стиле R1C1, указав адрес области ячеек в параметре RefersToR1C1.

Names Collection Object

Add Method

How to: Create New Named Ranges in Worksheets

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

Delphi:

    // объединим область ячеек "A1:C2" строки "вместе"
    ASheet.Range['A1:C2', EmptyParam].Merge(False);
    ASheet.Range['A1', EmptyParam].Select; // подправим вид курсора
    ASheet.Range['A1', EmptyParam].MergeArea.Formula := 'A1:C2 объединены';

    // объединим область ячеек "A3:C4" "раздельно" каждую строку

    ASheet.Range['A3:C4', EmptyParam].Merge(True);

    // определим, что ячейка C2 принадлежит объединенной области
    // при этом тестируем крайнюю ячейку области на вхождение

    if ASheet.Range['C2', EmptyParam].MergeCells then begin

    // если это так, то получим координаты области
      ASheet.Range['A3', EmptyParam].MergeArea.Formula := 'В стиле A1: ' +
        ASheet.Range['C2', EmptyParam].MergeArea.Address[True, True,
        xlA1, EmptyParam, EmptyParam];
      ASheet.Range['A4', EmptyParam].MergeArea.Formula :=
        Format('Начало в R%dC%d, конец в R%dC%d', [
          ASheet.Range['C2', EmptyParam].MergeArea.Row,
          ASheet.Range['C2', EmptyParam].MergeArea.Column,
          ASheet.Range['C2', EmptyParam].MergeArea.Row +
            ASheet.Range['C2', EmptyParam].MergeArea.Rows.Count - 1,
          ASheet.Range['C2', EmptyParam].MergeArea.Column +
            ASheet.Range['C2', EmptyParam].MergeArea.Columns.Count - 1

        ]);
    end;

Смотрите дальше, как сделать автоподбор высоты строк для объединенных ячеек.

MergeCells Property

MergeArea Property

Merge Method

UnMerge Method

Как записывать данные из вариантного массива в Excel?

Запись данных из вариантного массива (VarArray) очень хорошо расписана в статьях «По волнам интеграции… III» и «Зарисовка на тему экспорта в Excel». Для разнообразия, приведу еще раз этот вариант быстрого экспорта в Excel.

Внимание! Если вы пытаетесь записать в область одну строку, то МАССИВ все равно ДОЛЖЕН БЫТЬ ДВУМЕРНЫМ! Т.е. varData := VarArrayCreate([1, 1, 1, ColumnCount], varVariant); При записи массива вы должны указать в адресе области ячеек Range ВСЮ область для заполнения.

Delphi:

procedure CopyFromDataSet(ASheet: _WorkSheet; DataSet: TDataSet);

var
  R, C: Integer;
  vData: Variant;
begin
  DataSet.Last; // специально для IBX
  // строки на одну больше, чем в датасете - для шапки
  vData := VarArrayCreate([0, DataSet.RecordCount, 1, DataSet.FieldCount], varVariant);
  for C := 0 to DataSet.FieldCount - 1 do

    vData[0, C + 1] := DataSet.Fields[C].DisplayLabel;
  DataSet.First;
  R := 1;
  while not DataSet.Eof do begin

    for C := 0 to DataSet.FieldCount - 1 do
      case DataSet.Fields[C].DataType of

        ftString, ftFixedChar, ftWideString:
          vData[R, C + 1] := #39 + DataSet.Fields[C].Value;
        else vData[R, C + 1] := DataSet.Fields[C].Value;
      end;
    Inc(R);
    DataSet.Next;
  end;
  // укажем всю область, в которую будут записаны данные из массива

  with ASheet do with Range['A1',
    Cells.Item[DataSet.RecordCount + 1, DataSet.FieldCount]] do begin

    Formula := vData;
    Borders.Weight := xlHairline;
    EntireColumn.AutoFit;
  end;
  vData := Unassigned; // освободим память сами
  // настройка внешнего вида
  with ASheet do Range['A1',
    Cells.Item[1, DataSet.FieldCount]].Interior.ColorIndex := 15;
  ASheet.Application.ActiveWindow.SplitRow := 1;
  ASheet.Application.ActiveWindow.FreezePanes := True;
  ASheet.Application.ActiveWindow.DisplayGridlines := False;

end;

C#:

      // данные будут взяты из таблицы EMPLOYEE из файла DBDEMOS.MDB
      string dbFile = Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFiles);
      dbFile += @"Borland SharedDatadbdemos.mdb";
      // заменим путь к файлу dbdemos
      dbFile = Regex.Replace(oleDbConnection1.ConnectionString,
        @"^(?<start>.*?;Data Source=)(?<db>[^;]*)(?<end>;.*)$",
        "${start}" + dbFile + "${end}");
      oleDbConnection1.ConnectionString = dbFile;
      try
      {
        oleDbDataAdapter1.Fill(dataSet1, "employee");
        oleDbConnection1.Close(); // закроем соединение
        //
        DataTable tblEmployee = dataSet1.Tables["employee"];
        dataGrid1.DataSource = tblEmployee; // dataSet1.Tables["employee"];
        // создадим двумерный массив для экспорта
        object[,] arrEmployee = (object[,]) Array.CreateInstance(typeof(object),
          new int[2] {tblEmployee.Rows.Count + 1, tblEmployee.Columns.Count}, // длины массива
          new int[2] {0, 1}); // начальные индексы строк и столбцов
        // заголовки
        for (int i = 0; i < tblEmployee.Columns.Count; i++)
          arrEmployee[0, i + 1] = tblEmployee.Columns[i].Caption;
        // данные
        for (int R = 0; R < tblEmployee.Rows.Count; R++)
          for (int C = 0; C < tblEmployee.Columns.Count; C++) {
            arrEmployee[R + 1, C + 1] = tblEmployee.Rows[R][C];
            Application.DoEvents();
          }
        Excel.Worksheet oSheet = null;
        Excel.Range oRng = null;
        Excel.Application XL = new Excel.Application();
        try
        {
          XL.Visible = true;
          XL.Interactive = false;
          XL.Workbooks.Add(Type.Missing);
          oSheet = (Excel.Worksheet) XL.ActiveSheet;
          oRng = oSheet.get_Range(oSheet.Cells[1, 1],
            oSheet.Cells[tblEmployee.Rows.Count + 1, tblEmployee.Columns.Count]);
          oRng.Formula = arrEmployee; // запись данных
          oRng.EntireColumn.AutoFit();
          oRng.Borders.LineStyle = Excel.XlLineStyle.xlContinuous;
          oRng.Borders.Weight = Excel.XlBorderWeight.xlHairline;
          // шапка
          oRng = oSheet.get_Range(oSheet.Cells[1, 1],
            oSheet.Cells[1, tblEmployee.Columns.Count]);
          oRng.Interior.ColorIndex = 15; // 25% серого
          oRng.Interior.Pattern = Excel.XlPattern.xlPatternSolid;
          XL.ActiveWindow.SplitRow = 1;
          XL.ActiveWindow.FreezePanes = true;
          XL.ActiveWindow.DisplayGridlines = false;
          XL.ActiveWorkbook.Saved = true;
          this.Activate();
        }
        finally
        {
          oSheet = null;
          XL.Interactive = true;
          XL.UserControl = true;
          XL = null;
        }
        dataSet1.Tables.Remove(tblEmployee);
      }
      catch (Exception ex)
      {
        if (oleDbConnection1.State == ConnectionState.Open) oleDbConnection1.Close();
        MessageBox.Show(ex.Message);
      }

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

Точно также, как и при экспорте, только самому создавать массив не нужно — Excel все сделает за вас. В принципе, после получения данных в массив, Excel уже не нужен, и от него можно отсоединиться.

Delphi:

var
  myVarArray: OleVariant;
…
  // массив будет создан автоматически

  MyVarArray := ASheet.UsedRange[lcid].Value[xlRangeValueDefault];
  // цикл по строкам
  for R := VarArrayLowBound(MyVarArray, 1) to VarArrayHighBound(MyVarArray, 1) do

  // цикл по столбцам
    for C := VarArrayLowBound(MyVarArray, 2) to VarArrayHighBound(MyVarArray, 2) do

C#:

// объявим пустой двумерный массив и получим в него данные
object[,] srcArr = (object[,]) ASheet.UsedRange.get_Value(
          Excel.XlRangeValueDataType.xlRangeValueDefault);
// цикл по массиву 
for (int R = srcArr.GetLowerBound(0); R <= srcArr.GetUpperBound(0); R++) 
  for (int C = srcArr.GetLowerBound(1); C <= srcArr.GetUpperBound(1); C++) 

Почему при выгрузке данных в Excel не могу записать строк больше 65536?

Потому что это максимально возможное количество строк объекта Worksheet. Если вы записываете больше строк, чем 65536, то помещайте их на следующий лист книги — благо, что количество листов ограничено только оперативной памятью комьютера.

Excel specifications and limits

Как писать в ячейки нескольких листов сразу?

Чтобы занести данные в несколько листов сразу, вы можете объединить листы методом Worksheets.Select и воспользоваться методом FillAcrossSheets

Delphi:

var
  SelSheets: Sheets;
…
    // заносим данные в активный лист

    XL.Range['B2', EmptyParam].Formula := 123.45;
    XL.Range['B3', EmptyParam].Borders.LineStyle := xlUnderlineStyleDouble;

    // выберем 4 листа, в которые будут сдублированы данные
    SelSheets := XL.ActiveWorkbook.Sheets[VarArrayOf([1, 2, 3, 4])] as Sheets;


//    SelSheets.Select(False, lcid); // не обязательно

    // заполним выбранные листы данными из активного листа из любой области ячеек
    SelSheets.FillAcrossSheets((XL.ActiveSheet as _Worksheet).UsedRange[lcid],
      xlFillWithAll, lcid);

Select Method

FillAcrossSheets Method

Как изменить цвет фона и шрифта ячейки?

Смотрите свойства Font и Interior объекта Range

Font Property

Interior Property

How to: Change Formatting in a Row that Contains a Selected Cell

Как изменить атрибуты шрифта части текста в ячейке (цвет, размер, имя)?

Чтобы изменить часть текста ячейки можно воспользоваться свойством Characters объекта Range.

Delphi:

Msg: String;
...
    Msg := ' Человек собаке друг J';
    // занесем тест в ячейку
    ASheet.Range['B3', EmptyParam].Formula := Msg;
    // займемся последним символом - изменим атрибуты шрифта
    ASheet.Range['B3', EmptyParam].Characters[Length(Msg), 1].Font.Name :=
      'Wingdings';
    ASheet.Range['B3', EmptyParam].Characters[Length(Msg), 1].Font.Size := 24;
    ASheet.Range['B3', EmptyParam].Characters[Length(Msg), 1].Font.Color := clBlue;

Characters Property

Как узнать позицию курсора в редактируемой по F2 ячейке или в строке формул и дописать в нее текст?

Никак! При входе в режим редактирования ячейки объект Excel.Application становится полностью недоступен через OLE.

XL97: Error Printing Microsoft Excel Section in a Binder

Как изменить выравнивание/угол наклона текста, отступы в ячейке?

Смотрите свойства HorizontalAlignment, VerticalAlignment, AddIndent и Orientation объекта Range

Delphi:

    ASheet.Range['B2', EmptyParam].HorizontalAlignment := xlLeft;
    ASheet.Range['B2', EmptyParam].VerticalAlignment := xlCenter;
    ASheet.Range['B2', EmptyParam].Orientation := 45; // 45 градусов
    // подберем ширину столбца

    ASheet.Range['B:B', EmptyParam].Columns.AutoFit;
//    ASheet.Range['B2', EmptyParam].EntireColumn.AutoFit;

HorizontalAlignment Property

VerticalAlignment Property

Orientation Property

AddIndent Property

IndentLevel Property

Как задать границы для области ячеек (Borders)?

Смотрите свойство Borders объекта Range.

Delphi:

// нарисуем рамку вокруг "B2"
    ASheet.Range['B2', EmptyParam].BorderAround(
        xlContinuous,
        xlThick,
        xlColorIndexAutomatic,
        EmptyParam
      );

    // нарисуем границу сверху

    ASheet.Range['A7:А7', EmptyParam].Borders[xlEdgeTop].LineStyle := xlContinuous;
    ASheet.Range['A7:E7', EmptyParam].Borders[xlEdgeTop].Weight := xlMedium;

Перенос VBA-макросов в Delphi

Borders Property

BorderAround Method

Как скопировать форматы и формулы из строки в нижележащую область (AutoFill)?

Это как раз самый удобный метод копирования форматов и формул для расширения области данных при использовании шаблонов. Подразумевается, что между НАЧАЛО/КОНЕЦ находятся подготовленные ячейки шаблона (форматирование, именованная область DataRange для данных).

Delphi:

    // НАЧАЛО ШАБЛОНА
    // шапка
    ASheet.Range['A1', EmptyParam].Formula := 'Шапка';
    // таблица

    ASheet.Range['A2', EmptyParam].Formula := '#';
    ASheet.Range['B2', EmptyParam].Formula := 'Имя';
    ASheet.Range['C2', EmptyParam].Formula := 'Кол-во';
    ASheet.Range['D2', EmptyParam].Formula := 'Цена';
    ASheet.Range['E2', EmptyParam].Formula := 'Сумма';
    ASheet.Range['A2:E2', EmptyParam].BorderAround(
        xlContinuous,
        xlHairline,
        xlColorIndexAutomatic,
        EmptyParam
      );
    // сделаем вид, что у нас уже готова строка шаблона данных

    // и зададим форматы и формулы
    ASheet.Range['A3', EmptyParam].Font.Bold := True;
    ASheet.Range['C3', EmptyParam].Formula := '=round(rand()*10+1,0)';
    ASheet.Range['D3', EmptyParam].Formula := '=round(rand()*100,2)';

    // в случаях формул удобно использовать стил R1C1

    ASheet.Range['E3', EmptyParam].FormulaR1C1 := '=round(RC[-1]*RC[-2],2)';
    ASheet.Range['E3', EmptyParam].NumberFormat := '#,##0.00';

    // пустая строка для того, чтоб сумма считалась автоматом
    ASheet.Range['A4', EmptyParam].EntireRow.Hidden := True;

    // добавим итоговую сумму (с пустой строкой)

    ASheet.Range['E5', EmptyParam].FormulaR1C1 := '=sum(R[-1]C:R[-2]C)';
    ASheet.Range['E5', EmptyParam].Font.Bold := True;
    ASheet.Range['A5:E5', EmptyParam].Borders[xlEdgeTop].LineStyle :=
      xlContinuous;
    ASheet.Range['A5:E5', EmptyParam].Borders[xlEdgeTop].Weight := xlMedium;

    // области данных присвоим имя
    (ASheet.Parent as ExcelWorkbook).Names.Add(
      'DataRange', // Name,

      ASheet.Range['A3:E3', EmptyParam], // RefersTo: OleVariant;
      True, // Visible: OleVariant;
      EmptyParam, // MacroType: OleVariant;
      EmptyParam, // ShortcutKey: OleVariant;

      EmptyParam, // Category: OleVariant;
      EmptyParam, // NameLocal: OleVariant;
      EmptyParam, // RefersToLocal: OleVariant;
      EmptyParam, // CategoryLocal: OleVariant;
      EmptyParam, // RefersToR1C1: OleVariant;

      EmptyParam // RefersToR1C1Local: OleVariant
    );
    ASheet.Range['DataRange', EmptyParam].Borders[xlEdgeBottom].LineStyle :=
      xlContinuous;
    ASheet.Range['DataRange', EmptyParam].Borders[xlEdgeBottom].Weight := xlHairline;
    // КОНЕЦ ШАБЛОНА

    // Начало работы с шаблоном
    // Добавим 4 строки для занесения данных (итого уже 5 строк для данных)

    // Неудобство при использовании Cells в Range - обязательное
    // дублирование Cells во втором параметре
    ASheet.Range[
      ASheet.Cells.Item[ASheet.Range['DataRange', EmptyParam].Row + 1, 1],
      ASheet.Cells.Item[ASheet.Range['DataRange', EmptyParam].Row + 4, 1]
    ].EntireRow.Insert(xlShiftDown, EmptyParam);

    // теперь заполним область форматированием, захватив (ОБЯЗАТЕЛЬНО)

    // и область-шаблон "DataRange"
    ASheet.Range['DataRange', EmptyParam].AutoFill(
      ASheet.Range[
        // захватим область источника
        ASheet.Cells.Item[ASheet.Range['DataRange', EmptyParam].Row, 1],
        ASheet.Cells.Item[ASheet.Range['DataRange', EmptyParam].Row + 5,
        ASheet.Range['DataRange', EmptyParam].Columns.Count]
      ],
      xlFillCopy
    );

    // заносим данные из массива (номер и имя) - 5 строк, 2 столбца

    arrData := VarArrayCreate([1, 5, 1, 2], varVariant);
    for i := 1 to 5 do begin

      arrData[i, 1] := i;
      arrData[i, 2] := Format('Имя %d', [i]);
    end;
    ASheet.Range[
      ASheet.Cells.Item[ASheet.Range['DataRange', EmptyParam].Row, 1],
      ASheet.Cells.Item[ASheet.Range['DataRange', EmptyParam].Row + 5, 2]
    ].Formula := arrData;

AutoFill Method

How to: Copy Data and Formatting across Worksheets

Как скопировать область ячеек с сохранением всех форматов? Как скопировать только значения ячейки?

Метод Copy позволяет не только копировать содержимое области ячеек в буфер обмена (при пустом параметре), но и задать конкретный адрес ячеек для копирования. Если вы хотите вставить из буфера только некоторые параметры скопированной в БО ячейки, то для вставки используйте метод PasteSpecial, указав необходимый XlPasteType (первый аргумент).

Delphi:

    R := ASheet.Range['A1', EmptyParam];
    // скопируем ячейку "A1" в "C3" - напрямую в ячейку

    R.Copy(ASheet.Range['C3', EmptyParam]); // текущий лист
    // в соседний лист
    R.Copy((XL.Sheets[2] as _Worksheet).Range['C3', EmptyParam]);

    // скопируем через буфер обмена

    R.Copy(EmptyParam); // поместим в БО

    // вставим в ячейку "C3" в текущем листе
    ASheet.Paste(ASheet.Range['C5', EmptyParam], EmptyParam, lcid);
    // в соседний лист

    (XL.Sheets[2] as _Worksheet).Paste(
      (XL.Sheets[2] as _Worksheet).Range['C5', EmptyParam], EmptyParam, lcid);

    // вставляем только значение ячейки без форматирования
    ASheet.Range['C7', EmptyParam].PasteSpecial(xlPasteValues,
      xlPasteSpecialOperationNone, False, False);

Copy Method

PasteSpecial Method

Paste Method

CutCopyMode Property

Как скопировать область, чтобы сохранились размеры строк/столбцов?

К сожалению, при копировании не сохраняются размеры строк и столбцов. Для сохранения размеров строк и столбцов можно использовать несколько способов:

Delphi:

    // способ первый - использование метода PasteSpecial
    // скопируем область ячеек в буфер обмена
    R.Copy(EmptyParam); // поместим в БО
    // вставим в "C3" - ширина колонки не изменилась

    ASheet.Paste(ASheet.Range['C5', EmptyParam], EmptyParam, lcid);
    // специальная свтавка с XlPasteType = xlPasteColumnWidths
    ASheet.Range['C5', EmptyParam].PasteSpecial(xlPasteColumnWidths,
      xlPasteSpecialOperationNone, False, False);

    // второй способ - обращение к коллекциям Rows и Columns
    // копируем весь/все столбец(ы)
    R.EntireColumn.Copy(EmptyParam); // поместим в БО

    // обязательно должна быть указана первая строка!
    ASheet.Paste(ASheet.Range['E1', EmptyParam], EmptyParam, lcid);

    // третий способ - "копирование" свойства ColumnWidth
    R.Copy(ASheet.Range['G4', EmptyParam]);
    // Просто "копируем" ширину столбца

    ASheet.Range['G4', EmptyParam].ColumnWidth := R.ColumnWidth;

Copy Method

PasteSpecial Method

Как сделать автоперенос строк в ячейке?

Чтобы сделать перенос слов в ячейке, установите свойство WrapText объекта Range.

Delphi:

    ASheet.Range['A1', EmptyParam].WrapText := True;
    ASheet.Range['A1', EmptyParam].EntireRow.AutoFit;

WrapText Property

Как вставить несколько строк/столбцов? Как удалить несколько строк/столбцов? Как прятать/показывать строки и столбцы? Как программно изменить высоту строки или ширину столбца?

Delphi:

    // заполним ячейки данными для наглядности
    ASheet.Range['A1', EmptyParam].Formula := 1;
    R := ASheet.Range['A1:A25', EmptyParam];
    R.DataSeries(xlColumns, xlLinear, xlDay, 1, EmptyParam, EmptyParam);
    R := ASheet.Range['A1:O1', EmptyParam];
    R.DataSeries(xlRows, xlLinear, xlDay, 1, EmptyParam, EmptyParam);

    // не забывайте указывать EntireRow и EntireColumn!

    // добавим пять пустых строк после 20-й строки
    ASheet.Range['21:25', EmptyParam].EntireRow.Insert(xlShiftDown, EmptyParam);

    // удвоим ширину второго и третьего столбцов
    ASheet.Range['B:C', EmptyParam].EntireColumn.ColumnWidth :=
      ASheet.Range['B:C', EmptyParam].EntireColumn.ColumnWidth * 2;
    // удвоим высоту второй и третьей строки

    ASheet.Range['2:3', EmptyParam].EntireRow.RowHeight :=
      ASheet.Range['2:3', EmptyParam].EntireRow.RowHeight * 2;

    // удалим 4, 6 и 8 столбцы (два способа - кому что понравится)
//    ASheet.Range['D:D,F:F,H:H', EmptyParam].EntireColumn.Delete(xlShiftToLeft);
    ASheet.Range['D1,F1,H1', EmptyParam].EntireColumn.Delete(xlShiftToLeft);

ColumnWidth

RowHeight Property

Insert Method

Delete Method

Как подогнать высоту или ширину ячеек для отображения всего текста?

Для отображения всего текста в ячейке или области ячеек используйте метод AutoFit объекта Range.

Delphi:

// для строки
ASheet.Range['A1', EmptyParam].EntireRow.AutoFit;
// для столбца
ASheet.Range['A1', EmptyParam].EntireColumn.AutoFit;

AutoFit Method

ShrinkToFit Property

Как сделать автоподбор высоты строк для объединенных ячеек?

Как известно, метод AutoFit для подбора высоты объединенных ячеек не срабатывает. Для этого был придуман простой метод (взят отсюда и просто адаптирован под Delphi). Работает для объединенных ячеек в одной строке. Просто укажите одну из объединенных ячеек области (свойство WrapText должно быть включено).

Delphi:

  procedure AutoFitMergedCellRowHeight(Rng: ExcelRange);
  var

    mergedCellRgWidth: Single;
    rngWidth, possNewRowHeight: Single;
    i: Integer;
  begin
    if Rng.MergeCells then begin
      // здесь использована самописная функция перевода стиля R1C1 в A1
      if xlRCtoA1(Rng.Row, Rng.Column) = xlRCtoA1(
        Rng.Range['A1', EmptyParam].Row, Rng.Range['A1', EmptyParam].Column)
        then Rng := Rng.MergeArea;
      with Rng do begin

        if (Rows.Count = 1) and (WrapText) then begin
          (Rng.Parent as _Worksheet).Application.ScreenUpdating[lcid] := False;
          rngWidth := Cells.Item[1, 1].ColumnWidth;
          mergedCellRgWidth := 0;
          for i := 1 to Columns.Count do

            mergedCellRgWidth := Cells.Item[1, i].ColumnWidth + MergedCellRgWidth;
          MergeCells := False;
          Cells.Item[1, 1].ColumnWidth := MergedCellRgWidth;
          EntireRow.AutoFit;
          possNewRowHeight := RowHeight;
          Cells.Item[1, 1].ColumnWidth := rngWidth;
          MergeCells := True;
          RowHeight := possNewRowHeight;
          (Rng.Parent as _Worksheet).Application.ScreenUpdating[lcid] := True;
        end; // if

      end; // with
    end; // if
  end; // procedure

// вызов

AutoFitMergedCellRowHeight(ASheet.Range['F3', EmptyParam]);

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

Как программно «заморозить» строки/столбцы?

Delphi:

      // Отделить 3 строки
      XL.ActiveWindow.SplitRow := 3;
      // Отделить 1 колонку
      XL.ActiveWindow.SplitColumn := 1;
      // заморозим
      XL.ActiveWindow.FreezePanes := True;

FreezePanes Property

SplitColumn Property

SplitRow Property

Split Property

Как добавить примечание к ячейке? Как удалить примечание? Как изменить атрибуты шрифта примечания?

Комментарий — это своеобразный объект Shape, привязанный к определенному объекту Range.

Delphi:

    // Добавление примечания
    // Способ первый
    ASheet.Range['A1', EmptyParam].AddComment('Note:'#10'Hello A1!');
    // Способ второй

    ASheet.Range['A2', EmptyParam].NoteText('Note:'#10'Hello A2!', EmptyParam, EmptyParam);

    // Изменим атрибуты части текста примечания
    // обращаясь к свойствам Shape.TextFrame.Characters,
    // т.е. Comment - это некий объект Shape
    with ASheet.Range['A1', EmptyParam].Comment.Shape.TextFrame.Characters(
    // если не указать длину, то от заданной позиции и до конца текста

      7, EmptyParam) do begin
      Font.Bold := False;
      Font.Color := clNavy;
    end;

    // добавим третью строку к коментарию в A2
    ASheet.Range['A2', EmptyParam].NoteText(
      ASheet.Range['A2', EmptyParam].NoteText(EmptyParam,
      EmptyParam, EmptyParam) + #10'Третяя строка',
      EmptyParam, EmptyParam);

    // или так

    ASheet.Range['A2', EmptyParam].Comment.Text(
      ASheet.Range['A2', EmptyParam].Comment.Text(EmptyParam,
      EmptyParam, EmptyParam) + #10'Третяя строка',
      EmptyParam, EmptyParam);

    // можно показывать комментарий все время, как транспарант
    ASheet.Range['A2', EmptyParam].Comment.Visible := True; // False

    // теперь просто удалим комментарий
    ASheet.Range['A1', EmptyParam].Comment.Delete;

    // или так
    ASheet.Range['A1', EmptyParam].ClearNotes;

Comment Property

AddComment Method

NoteText Method

ClearNotes Method

How to: Add, Delete, and Display Worksheet Comments

Как добавить URL? Как сделать гиперссылку для рисунка?

Delphi:

    // добавим гиперссылки в A7 и A8

    with ASheet do Hyperlinks.Add(
      Range['A7', EmptyParam],
      'http://www.delphikingdom.com/asp/section.asp?id=16',
      EmptyParam,
      'Все материалы раздела'#10'Hello, World!',
      'Hello, World!');
    with ASheet do Hyperlinks.Add(
      Range['A8', EmptyParam],
      'http://www.delphikingdom.com/asp/nets.asp',
      EmptyParam,
      'Верхний уровень "Дерева тем"'#10'тематического каталога',
      'Тематический каталог');

    // вставим рисунок в текущую ячейку и создадим гиперсылку

    Pic := (ASheet.Pictures(EmptyParam, lcid) as Pictures).Insert(
      MyPicsPath + 'common.gif', EmptyParam);

    ASheet.Hyperlinks.Add(
      Pic.ShapeRange.Item(1),
      'http://www.delphikingdom.com/',
      EmptyParam,
      'Королевство Delphi',
      EmptyParam);

    // редактирование
    with ASheet.Range['A8', EmptyParam].Hyperlinks.Item[1] do begin

      Address := 'http://www.delphikingdom.com/asp/answer.asp?IDAnswer=23150';
      ScreenTip := 'Вопроc ¹ 23150';
      TextToDisplay := 'Как в Excel редактировать гиперссылки, содержащиеся в ячейках?';
    end;

    // удалим гиперссылку - останется только тект, указанный в TextToDisplay
    ASheet.Range['A8', EmptyParam].Hyperlinks.Item[1].Delete;

Hyperlinks Property

Hyperlinks Collection

Hyperlink Object

Как отсортировать область ячеек?

Пример сортировки всех данных на листе по первому, второму и третьему столбцам.

Delphi:

      ASheet.UsedRange[lcid].Sort(
      ASheet.Range['A1', EmptyParam], // Key1: OleVariant;
      xlAscending, // Order1: XlSortOrder;
      ASheet.Range['B1', EmptyParam], // Key2: OleVariant;
      EmptyParam, // xlSortValues

      xlAscending, // Order2: XlSortOrder;
      ASheet.Range['C1', EmptyParam], // Key3: OleVariant;
      xlAscending, // Order3: XlSortOrder;
      xlGuess, // Header: XlYesNoGuess;

      EmptyParam, // OrderCustom: OleVariant;
      False, // MatchCase: OleVariant;
      xlTopToBottom, // Orientation: XlSortOrientation;
      xlStroke // SortMethod: XlSortMethod
    );

Sort Method

How to: Sort Data in Worksheets Programmatically

Как сделать поиск значений в области ячеек или по всему листу?

Для поиска в области ячеек задайте диапазон ячеек при получении ссылки на объект Range. Если нужно искать по всему листу, то укажите UsedRange или просто одну ячейку, например «A1». Метод Find и FindNext возвращают объект Range, если значение найдено, и, если ничего не найдено, то nil (или null в C#).

Delphi:

var R: ExcelRange;
...
    S := '77';
    R := ASheet.UsedRange[lcid].Find(
      S, // What: OleVariant;
      EmptyParam, // After: OleVariant;
      xlValues, // LookIn: OleVariant;
      xlPart, // LookAt: OleVariant;

      xlByRows, // SearchOrder: OleVariant;
      xlNext, // SearchDirection: XlSearchDirection;
      False, // MatchCase: OleVariant;
      False, //MatchByte: OleVariant
      // нужно установить в True, если

      EmptyParam // SearchFormat: OleVariant
    );

    // поиск был завершен удачно, если определен объект R
    // поиск следующих ячеек с искомым текстом
    if Assigned(R) then begin

      Addr := R.Address[True, True, xlA1, EmptyParam, EmptyParam];
      repeat
        // зальем красным цветом найденные ячейки
        R.Interior.Color := RGB(255, 0, 0);
        R.Font.Color := RGB(255, 255, 220);
        // найдем следующую

        R := ASheet.UsedRange[lcid].FindNext(R);
        if Assigned(R)
          then Addr2 := R.Address[True, True, xlA1, EmptyParam, EmptyParam];
        // выход, если не найдено или адрес совпал (круг завершен)
      until not Assigned(R) or SameText(Addr, Addr2);
    end;

Find Method

FindNext Method

CellFormat Object

How to: Search for Text in Worksheet Ranges

Как, имея ссылку на ячейку, узнать имя листа, которому она принадлежит? Узнать имя книги?

Получить ссылку на объект Worksheet, содержащий данную ячейку можно из свойства Parent.

var R: ExcelRange;
...
    // получим имя листа
    R.Formula := 'Имя листа: ' + (R.Parent as _Worksheet).Name;

    // получим имя книги
    R.Offset[1, 0].Formula := 'Имя книги: ' +
      ((R.Parent as _Worksheet).Parent as _Workbook).Name;

    // получим имя книги с полным путем к ней

    R.Offset[2, 0].Formula := 'Полное имя книги: ' +
      ((R.Parent as _Worksheet).Parent as _Workbook).FullName[lcid];

    // из ячейки к объекту Excel.Application доступ только через Worksheet

    R.Offset[3, 0].Formula :=
      (R.Parent as _Worksheet).Application.OperatingSystem[lcid];

Parent Property

Полезные ссылки

Microsoft.Office.Interop.Excel Namespace

Microsoft Excel Object Model [Excel 2003 VBA Language Reference]

Automating Excel Using the Excel Object Model

Office Development — Excel

Migrating Excel VBA Solutions to Visual Studio 2005 Tools for Office

Converting Microsoft Office VBA Macros to Visual Basic .NET and C#

Microsoft Excel 2003 Language Reference

Understanding the Excel Object Model from a .NET Developer’s Perspective

Microsoft Excel Tip

Answers to Frequently Asked Questions about Microsoft Excel

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

Sub Название_Макроса()

'Выделить диапазон который необходимо скопировать
Range("A1:F52").Select
'Скопировать то, что выделено
Selection.Copy
ChDir "путь к папке где лежит файл в который необходимо скопировать"
Workbooks.Open Filename:= "Название файла, который находится в папке, путь к которой указан выше"
'Выделить начальную ячейку в которую необходимо вставить скопированные данные
Range("A6").Select
'Вставить данные
ActiveSheet.Paste
'сохранить текущую книгу
ActiveWorkbook.Save
'Закрыть книгу
ActiveWorkbook.Close
End Sub

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

Sub Название_Макроса2()
'Открываем файл с которого нужно скопировать данные
Workbooks.Open Filename:="C:Данные.xlsx"

'Скопировать нужный диапазон в открывшейся книге на листе 1
Workbooks("Данные.xlsx").Worksheets("Лист1").Range("A16:E16").Copy
'Активируем нужную нам книгу
Workbooks("Книга1.xlsm").Activate

'Выделяем и вставляем скопированные данные в ячейку А1
ActiveWorkbook.Worksheets("Лист1").Range("A1").Select
ActiveSheet.Paste

'Закрываем книгу откуда мы скопировали данные
Workbooks("Данные.xlsx").Close

End Sub

Еще пример — Скопировать диапазоны данных из активной открытой книги Excel нескольких листов (в нашем примере 3-х листов) в другую книгу, которая хранится в определенном месте. Данные будут вставлены как значения, плюс будут перенесены форматы ячеек.

Sub Копируем_листы_в_другую_книгу()
Dim bookconst As Workbook
Dim abook As Workbook
Set abook = ActiveWorkbook 'присваиваем перменную активной книге
Set bookconst = Workbooks.Open("C:UsersUserDesktop1.xlsx") 'присваиваем перменную книге куда необходимо копировать данные

'переходим в активную книгу откуда необходимо скопировать данные
abook.Worksheets("Лист1").Activate
Range("A1:I23").Copy 'копируем определенный диапазон листа, укажите свой диапазон
bookconst.Worksheets("Лист1").Activate 'активируем лист куда необходимо вставить данные
Range("A1:I23").Select 'встаем на ячейку А1
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
'вставляем только форматы ячеек
Selection.PasteSpecial Paste:=xlPasteFormats, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=False
'второй лист
abook.Worksheets("Лист2").Activate
Range("A1:I23").Copy
bookconst.Worksheets("Лист2").Activate
Range("A1:I23").Select 'выделяем диапазон
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
'вставляем только форматы ячеек
Selection.PasteSpecial Paste:=xlPasteFormats, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=False
'третий лист
abook.Worksheets("Лист3").Activate
Range("A1:I23").Copy
bookconst.Worksheets("Лист3").Activate
Range("A1:I23").Select 'выделяем диапазон
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
'вставляем только форматы ячеек
Selection.PasteSpecial Paste:=xlPasteFormats, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=False
'сохранить текущую книгу
bookconst.Save
'Закрыть книгу
bookconst.Close
abook.Activate

End Sub

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

Спасибо за внимание.

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

  В связи с этим я решил прикрепить файл с которым я работаю. По сути дела мне надо преобразовать данные, содержащиеся на Листе 1 согласно примеру на Листе 2. Проблема у меня возникает, когда я пытаюсь перенести информацию из 3ий строки (Period X) на Лист 2 в Столбец J. Я попробовал конструкцию With – End With, предложенную Юрием, но она не сработала.    

  Sub Reformatin_Fcst_with_Jugmt()  
   Dim i As Integer, rgX As Range, rgX2 As Range, DetFields As Range  
   Dim intNumRow As Integer, intNumRow2 As Integer, intNumCol As Integer  

         Worksheets(«Sheet2»).Cells.Clear  
   Worksheets(«Sheet2»).Range(«B1»).Value = «Project + Period»  
   Worksheets(«Sheet2»).Range(«C1»).Value = «WBS Org Level 2»  
   Worksheets(«Sheet2»).Range(«D1»).Value = «Project»  
   Worksheets(«Sheet2»).Range(«E1»).Value = «Project2»  
   Worksheets(«Sheet2»).Range(«F1»).Value = «PRJ Customer2»  
   Worksheets(«Sheet2»).Range(«G1»).Value = «PRJ Resp Person2»  
   Worksheets(«Sheet2»).Range(«H1»).Value = «PRJ Admin2»  
   Worksheets(«Sheet2»).Range(«I1»).Value = «Fiscal Quarter»  
   Worksheets(«Sheet2»).Range(«J1»).Value = «Fiscal year/period»  
   Worksheets(«Sheet2»).Range(«K1»).Value = «Plan Revenue»  
   Worksheets(«Sheet2»).Range(«L1»).Value = «Plan Total Incurred Cost»  
   Worksheets(«Sheet2»).Range(«M1»).Value = «EGM%»  

         Set rgX = Range(«a1»).End(xlDown).Offset(-1)  
   Set rgX2 = Worksheets(«Sheet2»).Range(«a2»)  
   intNumRow = Range(«a1»).End(xlDown).CurrentRegion.Rows.Count  
   Set DetFields = Range(Cells(Range(«a1»).End(xlDown).Row + 1, 1), Cells(intNumRow, 5))  
   For i = 1 To Application.WorksheetFunction.CountIf(Rows(«3:3»), «Period*»)  
       Set rgX = Rows(«3:3″).Find(What:=»Period», After:=rgX)  
       DetFields.Copy Worksheets(«Sheet2»).Cells(rgX2.Row, rgX2.Column + 2)  
       Range(Cells(rgX.Row + 2, rgX.Column), Cells(intNumRow, rgX.Column + 1)).Copy _  
       Worksheets(«Sheet2»).Cells(rgX2.Row, rgX2.Column + 10)  
       intNumRow2 = rgX2.Offset(0, 2).End(xlDown).CurrentRegion.Rows.Count  

                 With Sheets(«Sheet2»)  
           rgX.Copy .Range(Cells(rgX2.Row, rgX2.Column + 9), Cells(intNumRow2, rgX2.Column + 9))  
       End With  

             Set rgX2 = Worksheets(«Sheet2»).Cells(intNumRow2 + 1, 1)  
   Next i  
End Sub  

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

Содержание

  • Выбор ячейки / диапазона в Excel с помощью VBA
  • Копирование ячеек / диапазонов с помощью VBA
  • Назначение диапазонов объектным переменным
  • Введите данные в следующую пустую ячейку (используя поле ввода)
  • Цикл по ячейкам / диапазонам
  • Куда поместить код VBA

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

А если вы хотите автоматизировать свою работу в Excel с помощью VBA, вам нужно знать, как работать с ячейками и диапазонами с помощью VBA.

С диапазонами в VBA можно делать много разных вещей (например, выбирать, копировать, перемещать, редактировать и т. Д.).

Чтобы охватить эту тему, я разделю это руководство на разделы и покажу вам, как работать с ячейками и диапазонами в Excel VBA на примерах.

Давайте начнем.

Все коды, которые я упоминаю в этом руководстве, необходимо поместить в редактор VB. Перейдите в раздел «Где разместить код VBA», чтобы узнать, как это работает.

Если вы заинтересованы в изучении VBA простым способом, ознакомьтесь с моими Онлайн-обучение по Excel VBA.

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

В большинстве случаев лучше не выбирать ячейки или диапазоны (как мы увидим).

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

Итак, давайте начнем с очень простого примера.

Выбор отдельной ячейки с помощью VBA

Если вы хотите выбрать одну ячейку на активном листе (скажем, A1), вы можете использовать приведенный ниже код:

Sub SelectCell () Диапазон ("A1"). Выберите End Sub

В приведенном выше коде есть обязательные части «Sub» и «End Sub», а также строка кода, которая выбирает ячейку A1.

Диапазон («A1») сообщает VBA адрес ячейки, на которую мы хотим сослаться.

Выбирать является методом объекта Range и выбирает ячейки / диапазон, указанные в объекте Range. Ссылки на ячейки необходимо заключать в двойные кавычки.

Этот код покажет ошибку, если лист диаграммы является активным. Лист диаграммы содержит диаграммы и не используется широко. Поскольку в нем нет ячеек / диапазонов, приведенный выше код не может выбрать его, и в результате будет отображаться ошибка.

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

Но если вы хотите выделить ячейку на другом листе (скажем, Sheet2), вам нужно сначала активировать Sheet2, а затем выбрать ячейку в нем.

Sub SelectCell () Worksheets ("Sheet2"). Активируйте диапазон ("A1"). Выберите End Sub

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

Sub SelectCell () Рабочие книги («Book2.xlsx»). Рабочие листы («Sheet2»). Активировать диапазон («A1»). Выберите End Sub 

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

Эти примеры не очень полезны, но позже в этом руководстве вы увидите, как мы можем использовать те же концепции для копирования и вставки ячеек в Excel (с использованием VBA).

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

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

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

Посмотрим, как это сделать.

Выбор диапазона фиксированного размера

Вот код, который выберет диапазон A1: D20.

Sub SelectRange () Диапазон ("A1: D20"). Выберите End Sub 

Другой способ сделать это — использовать приведенный ниже код:

Sub SelectRange () Диапазон ("A1", "D20"). Выберите End Sub

Приведенный выше код берет адрес верхней левой ячейки (A1) и адрес нижней правой ячейки (D20) и выбирает весь диапазон. Этот метод становится полезным, когда вы работаете с диапазонами переменного размера (как мы увидим, когда позже в этом руководстве будет рассмотрено свойство End).

Если вы хотите, чтобы выбор происходил в другой книге или на другом листе, вам необходимо сообщить VBA точные имена этих объектов.

Например, приведенный ниже код выберет диапазон A1: D20 на листе Sheet2 в книге Book2.

Sub SelectRange () Рабочие книги ("Book2.xlsx"). Рабочие листы ("Sheet1"). Активировать диапазон ("A1: D20"). Выбрать End Sub

А что, если вы не знаете, сколько там строк. Что, если вы хотите выбрать все ячейки, в которых есть значение.

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

Выбор диапазона переменного размера

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

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

Выберите с помощью свойства CurrentRange

В случаях, когда вы не знаете, сколько строк / столбцов содержат данные, вы можете использовать свойство CurrentRange объекта Range.

Свойство CurrentRange охватывает все смежные заполненные ячейки в диапазоне данных.

Ниже приведен код, который выберет текущий регион, содержащий ячейку A1.

Sub SelectCurrentRegion () Диапазон ("A1"). CurrentRegion.Select End Sub

Вышеупомянутый метод хорош, когда у вас есть все данные в виде таблицы без пустых строк / столбцов в ней.

Но если у вас есть пустые строки / столбцы в ваших данных, он не будет выбирать те, которые находятся после пустых строк / столбцов. На изображении ниже код CurrentRegion выбирает данные до строки 10, поскольку строка 11 пуста.

В таких случаях вы можете использовать свойство UsedRange объекта Worksheet.

Выберите с помощью свойства UsedRange

UsedRange позволяет ссылаться на любые измененные ячейки.

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

Sub SelectUsedRegion () ActiveSheet.UsedRange.Выберите End Sub

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

Выберите с помощью свойства конца

Теперь эта часть действительно полезна.

Свойство End позволяет выбрать последнюю заполненную ячейку. Это позволяет имитировать действие клавиш управления стрелками вниз / вверх или клавиш управления вправо / влево.

Попробуем разобраться в этом на примере.

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

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

Теперь давайте посмотрим, как это сделать с помощью VBA. Этот метод пригодится, когда вы хотите быстро перейти к последней заполненной ячейке в столбце переменного размера.

Sub GoToLastFilledCell () Диапазон ("A1"). End (xlDown). Выберите End Sub

Приведенный выше код перейдет к последней заполненной ячейке в столбце A.

Точно так же вы можете использовать End (xlToRight) для перехода к последней заполненной ячейке в строке.

Sub GoToLastFilledCell () Range ("A1"). End (xlToRight). Select End Sub

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

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

Sub SelectFilledCells () Range ("A1", Range ("A1"). End (xlDown)). Выберите End Sub

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

Вспомните приведенный выше пример, в котором мы выбрали диапазон A1: D20, используя следующую строку кода:

Диапазон («A1 ″,« D20 »)

Здесь A1 — это верхняя левая ячейка, а D20 — нижняя правая ячейка в диапазоне. Мы можем использовать ту же логику при выборе диапазонов переменного размера. Но поскольку мы не знаем точного адреса нижней правой ячейки, мы использовали свойство End, чтобы получить его.

В Range («A1», Range («A1»). End (xlDown)) «A1» относится к первой ячейке, а Range («A1»). End (xlDown) относится к последней ячейке. Поскольку мы предоставили обе ссылки, метод Select выбирает все ячейки между этими двумя ссылками.

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

Приведенный ниже код выберет все заполненные строки / столбцы, начиная с ячейки A1.

Sub SelectFilledCells () Range ("A1", Range ("A1"). End (xlDown) .End (xlToRight)). Выберите End Sub

В приведенном выше коде мы использовали Range («A1»). End (xlDown) .End (xlToRight), чтобы получить ссылку на заполненную нижнюю правую ячейку набора данных.

Разница между использованием CurrentRegion и End

Если вам интересно, зачем использовать свойство End для выбора заполненного диапазона, когда у нас есть свойство CurrentRegion, позвольте мне рассказать вам разницу.

С помощью свойства End вы можете указать начальную ячейку. Например, если у вас есть данные в формате A1: D20, но первая строка — это заголовки, вы можете использовать свойство End для выбора данных без заголовков (используя приведенный ниже код).

Sub SelectFilledCells () Range ("A2", Range ("A2"). End (xlDown) .End (xlToRight)). Выберите End Sub

Но CurrentRegion автоматически выберет весь набор данных, включая заголовки.

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

Теперь давайте посмотрим, как мы можем использовать эти методы для выполнения некоторой работы.

Копирование ячеек / диапазонов с помощью VBA

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

Начнем с простого примера.

Копирование одной ячейки

Если вы хотите скопировать ячейку A1 и вставить ее в ячейку D1, приведенный ниже код сделает это.

Sub CopyCell () Range ("A1"). Copy Range ("D1") End Sub

Обратите внимание, что метод копирования объекта диапазона копирует ячейку (точно так же, как Control + C) и вставляет ее в указанное место назначения.

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

Sub CopyCell () Range ("A1"). Место назначения копирования: = Range ("D1") End Sub

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

Как вы уже могли заметить, приведенный выше код копирует ячейку, не выбирая ее. Независимо от того, где вы находитесь на листе, код скопирует ячейку A1 и вставит ее в D1.

Также обратите внимание, что приведенный выше код перезапишет любой существующий код в ячейке D2. Если вы хотите, чтобы Excel сообщал вам, есть ли что-то в ячейке D1, не перезаписывая это, вы можете использовать приведенный ниже код.

Sub CopyCell () If Range ("D1") "" Then Response = MsgBox ("Вы хотите перезаписать существующие данные", vbYesNo) End If If Response = vbYes Then Range ("A1"). Copy Range ("D1" ") End If End Sub

Копирование диапазона фиксированного размера

Если вы хотите скопировать A1: D20 в J1: M20, вы можете использовать следующий код:

Sub CopyRange () Range ("A1: D20"). Copy Range ("J1") End Sub

В ячейке назначения вам просто нужно указать адрес верхней левой ячейки. Код автоматически скопирует точный скопированный диапазон в место назначения.

Вы можете использовать ту же конструкцию для копирования данных с одного листа на другой.

Приведенный ниже код скопирует A1: D20 с активного листа на Sheet2.

Sub CopyRange () Range ("A1: D20"). Копировать рабочие листы ("Sheet2"). Range ("A1") End Sub

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

Sub CopyRange () Worksheets ("Sheet1"). Range ("A1: D20"). Copy Worksheets ("Sheet2"). Range ("A1") End Sub

Преимущество приведенного выше кода заключается в том, что независимо от того, какой лист активен, он всегда копирует данные из Sheet1 и вставляет их в Sheet2.

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

Например, если у вас есть именованный диапазон под названием «SalesData», вы можете использовать приведенный ниже код, чтобы скопировать эти данные в Sheet2.

Sub CopyRange () Range ("SalesData"). Копировать рабочие листы ("Sheet2"). Range ("A1") End Sub

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

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

Sub CopyTable () Range ("Table1 [#All]"). Копировать рабочие листы ("Sheet2"). Range ("A1") End Sub

Вы также можете скопировать диапазон в другую рабочую книгу.

В следующем примере я копирую таблицу Excel (Table1) в книгу Book2.

Подложка CopyCurrentRegion () Range ("Table1 [#All]"). Копировать книги ("Book2.xlsx"). Worksheets ("Sheet1"). Range ("A1") End Sub

Этот код будет работать, только если рабочая книга уже открыта.

Копирование диапазона переменного размера

Один из способов скопировать диапазоны переменного размера — преобразовать их в именованные диапазоны или таблицу Excel и использовать коды, как показано в предыдущем разделе.

Но если вы не можете этого сделать, вы можете использовать свойство CurrentRegion или End объекта диапазона.

Приведенный ниже код скопирует текущую область на активном листе и вставит ее в Sheet2.

Подложка CopyCurrentRegion () Range ("A1"). CurrentRegion.Copy Worksheets ("Sheet2"). Range ("A1") End Sub

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

Sub CopyCurrentRegion () Range ("A1", Range ("A1"). End (xlDown)). Копировать рабочие листы ("Sheet2"). Range ("A1") End Sub

Если вы хотите скопировать как строки, так и столбцы, вы можете использовать приведенный ниже код:

Sub CopyCurrentRegion () Range ("A1", Range ("A1"). End (xlDown) .End (xlToRight)). Копировать рабочие листы ("Sheet2"). Range ("A1") End Sub

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

Назначение диапазонов объектным переменным

До сих пор мы использовали полный адрес ячеек (например, Workbooks («Book2.xlsx»). Worksheets («Sheet1»). Range («A1»)).

Чтобы сделать ваш код более управляемым, вы можете назначить эти диапазоны объектным переменным, а затем использовать эти переменные.

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

Sub CopyRange () Dim SourceRange As Range Dim DestinationRange As Range Set SourceRange = Worksheets ("Sheet1"). Range ("A1: D20") Set DestinationRange = Worksheets ("Sheet2"). Range ("A1") SourceRange.Copy DestinationRange Конец подписки

Начнем с объявления переменных как объектов Range. Затем мы назначаем диапазон этим переменным с помощью оператора Set. После того, как диапазон был назначен переменной, вы можете просто использовать переменную.

Введите данные в следующую пустую ячейку (используя поле ввода)

Вы можете использовать поля ввода, чтобы пользователь мог вводить данные.

Например, предположим, что у вас есть набор данных ниже, и вы хотите ввести запись о продажах, вы можете использовать поле ввода в VBA. Используя код, мы можем убедиться, что он заполняет данные в следующей пустой строке.

Sub EnterData () Dim RefRange As Range Set RefRange = Range ("A1"). End (xlDown) .Offset (1, 0) Set ProductCategory = RefRange.Offset (0, 1) Set Quantity = RefRange.Offset (0, 2 ) Set Amount = RefRange.Offset (0, 3) RefRange.Value = RefRange.Offset (-1, 0) .Value + 1 ProductCategory.Value = InputBox ("Категория продукта") Quantity.Value = InputBox ("Количество") Amount.Value = InputBox ("Amount") End Sub

Приведенный выше код использует поле ввода VBA для получения входных данных от пользователя, а затем вводит их в указанные ячейки.

Обратите внимание, что мы не использовали точные ссылки на ячейки. Вместо этого мы использовали свойства End и Offset, чтобы найти последнюю пустую ячейку и заполнить ее данными.

Этот код нельзя использовать. Например, если вы вводите текстовую строку, когда поле ввода запрашивает количество или сумму, вы заметите, что Excel позволяет это. Вы можете использовать условие If, чтобы проверить, является ли значение числовым или нет, и затем разрешить его соответственно.

Цикл по ячейкам / диапазонам

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

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

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

Вот код, который будет перебирать строки в выбранных ячейках и выделять альтернативные строки.

Sub HighlightAlternateRows () Dim Myrange As Range Dim Myrow As Range Set Myrange = Selection For Each Myrow In Myrange.Rows, если Myrow.Row Mod 2 = 0, то Myrow.Interior.Color = vbCyan End, если следующий Myrow End Sub

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

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

Sub HighlightAlternateRows () Dim Myrange As Range Dim Mycell As Range Set Myrange = Выбор для каждой ячейки Mycell в Myrange Если Mycell <0, то Mycell.Interior.Color = vbRed End, если следующий Mycell End Sub

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

Куда поместить код VBA

Хотите знать, где находится код VBA в вашей книге Excel?

В Excel есть серверная часть VBA, называемая редактором VBA. Вам необходимо скопировать и вставить код в окно кода модуля VB Editor.

Вот как это сделать:

  1. Перейдите на вкладку Разработчик.
  2. Выберите вариант Visual Basic. Это откроет редактор VB в бэкэнде.
  3. На панели Project Explorer в редакторе VB щелкните правой кнопкой мыши любой объект книги, в которую вы хотите вставить код.Если вы не видите Project Explorer, перейдите на вкладку View и нажмите Project Explorer.
  4. Перейдите во вкладку «Вставить» и нажмите «Модуль». Это вставит объект модуля для вашей книги.
  5. Скопируйте и вставьте код в окно модуля.

Like this post? Please share to your friends:
  • Excel скопировать ячейку на все ячейки в столбце
  • Excel скопировать ячейку заданное количество раз
  • Excel скопировать ячейку в другую книгу
  • Excel скопировать ячейки с форматом
  • Excel скопировать ячейки если