Перевод макроса Excel в синтаксис FoxPro

Исходный макрос Excel
Открытие листа Excel в FoxPro
Подключение механизма IntelliSens в FoxPro
Метод Select
Указание диапазона ячеек для функции
Указание произвольного диапазона ячеек
Когда использовать "запятую", а когда "точку с запятой"
Указание формата ячеек
Константы Excel
Именованные параметры функций Excel
Рисование рамки вокруг всех данных
Перенос слов, выравнивание, ширина столбца и высота строки

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

Для этого выбирается пункт меню Excel с именем "Сервис" - "Макрос" - "Начать запись". В появившемся окне указываем имя макроса (по умолчанию "Макрос1") и нажимаем кнопку "Ok". В результате, поверх листа Excel появляется маленькое специфическое окошко - ToolBar - с именем "Остановить запись" и все Ваши действия будут автоматически записываться.

После того, как Вы выполните все необходимые действия, остановите запись макроса. Для этого просто нажмите иконку с черным квадратиком в этом ToolBar с именем "Остановить запись". Далее выберите пункт меню Excel с именем "Сервис" - "Макрос" - "Макросы". Выберите имя только что записанного макроса (по умолчанию "Макрос1") и нажмите кнопку "Изменить".

Откроется окно редактора Micosoft Visual Basic в котором будет отображен код Вашего макроса. Это все замечательно, но возникает вопрос: как перевести то, что здесь написано в синтаксис FoxPro? И как вообще использовать это в FoxPro? Вот ответам на эти вопросы и посвящена данная статья.

Сразу замечу, что почти без изменений все приведенные советы можно применить к Word. Для примера выбран Excel потому, что в нем проще адресация. Весь лист разбит на ячейки, к которым собственно и ссылаемся.

Исходный макрос Excel

Сначала собственно создадим макрос, переводом которого позже и займемся. Откройте Excel, создайте новый файл и запустите запись макроса через пункт меню "Сервис" - "Макрос" - "Начать запись". Имя макроса оставьте в значении по умолчанию "Макрос1" и нажмите кнопку "Ok".

Далее заполняем лист Excel таким содержимым

Название
реквизита
Значение
реквизита
Первый 1 234,56
Второй 9 876,54
ИТОГО 11 111,10

Здесь сделано следующее:

  • Вся первая и последняя строка выделены жирным шрифтом
  • Содержимое всех ячеек первой строки переносится по словам
  • Для второго столбца установлен формат данных: числовой, два знака после запятой, пробел между тройками чисел
  • Также для второго столбца, точнее, только для числовых ячеек, установлен условный формат: выделить фон ячейки красным, если его содержимое меньше 2000
  • Последняя строка второго столбца содержит формулу суммирования содержимого всех строк таблицы по второму столбцу
  • Все заполненные ячейки обрамлены сеткой

Останавливаю запись макроса и смотрю, что же у меня получилось. Пункт меню "Сервис" - "Макрос" - "Макросы". Выбираю имя только что записанного макроса "Макрос1" и нажимаю кнопку "Изменить".


Sub Макрос1()
'
' Макрос1 Макрос
' Макрос записан 10.05.2005 (Максимов)
'

'
'   Ввод содержимого ячеек
    ActiveCell.FormulaR1C1 = "Название реквизита"
    Range("B1").Select
    ActiveCell.FormulaR1C1 = "Значение реквизита"
    Range("A2").Select
    ActiveCell.FormulaR1C1 = "Первый"
    Range("B2").Select
    ActiveCell.FormulaR1C1 = "1324.56"
    Range("A3").Select
    ActiveCell.FormulaR1C1 = "Второй"
    Range("B3").Select
    ActiveCell.FormulaR1C1 = "9876.54"
    Range("A4").Select
    ActiveCell.FormulaR1C1 = "ИТОГО"

'   Формула расчета итога
    Range("B4").Select
    ActiveCell.FormulaR1C1 = "=SUM(R[-2]C:R[-1]C)"

'   Выделение первой и последней строк жирным шрифтом
    Range("1:1,4:4").Select
    Range("A4").Activate
    Selection.Font.Bold = True

'   Установка формата для второго столбца
    Columns("B:B").Select
    Selection.NumberFormat = "#,##0.00"

'   Установка условного формата для числовых данных второго столбца
    Range("B2:B4").Select
    Selection.FormatConditions.Delete
    Selection.FormatConditions.Add Type:=xlCellValue, Operator:=xlLess, _
        Formula1:="2000"
    Selection.FormatConditions(1).Interior.ColorIndex = 3

'   Рисование рамки вокруг всех данных
    Range("A1:B4").Select
    Selection.Borders(xlDiagonalDown).LineStyle = xlNone
    Selection.Borders(xlDiagonalUp).LineStyle = xlNone
    With Selection.Borders(xlEdgeLeft)
        .LineStyle = xlContinuous
        .Weight = xlThin
        .ColorIndex = xlAutomatic
    End With
    With Selection.Borders(xlEdgeTop)
        .LineStyle = xlContinuous
        .Weight = xlThin
        .ColorIndex = xlAutomatic
    End With
    With Selection.Borders(xlEdgeBottom)
        .LineStyle = xlContinuous
        .Weight = xlThin
        .ColorIndex = xlAutomatic
    End With
    With Selection.Borders(xlEdgeRight)
        .LineStyle = xlContinuous
        .Weight = xlThin
        .ColorIndex = xlAutomatic
    End With
    With Selection.Borders(xlInsideVertical)
        .LineStyle = xlContinuous
        .Weight = xlThin
        .ColorIndex = xlAutomatic
    End With
    With Selection.Borders(xlInsideHorizontal)
        .LineStyle = xlContinuous
        .Weight = xlThin
        .ColorIndex = xlAutomatic
    End With

'   Установка формата данных для первой строки (перенос по словам и выравнивание)
    Rows("1:1").Select
    Selection.NumberFormat = "@"
    With Selection
        .HorizontalAlignment = xlCenter
        .VerticalAlignment = xlTop
        .WrapText = True
        .Orientation = 0
        .AddIndent = False
        .IndentLevel = 0
        .ShrinkToFit = False
        .ReadingOrder = xlContext
        .MergeCells = False
    End With

'   Уточнение ширины столбцов
    Columns("A:A").ColumnWidth = 11.57
    Columns("B:B").ColumnWidth = 10.14

'   Уточнение высоты первой строки
    Selection.RowHeight = 25.5

'   Переход на первую ячейку для сброса выделений
    Range("A1").Select
End Sub

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

Открытие листа Excel в FoxPro

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

Новый лист Excel открывается следующим образом


* Создаем объект Excel
LOCAL loExcel
loExcel=CREATEOBJECT('Excel.Application')

* Создаем в нем новую рабочую книгу
LOCAL loBook
#DEFINE xlWBATWorksheet -4167
loBook = m.loExcel.workbooks.Add(xlWBATWorksheet)

* Создаем ссылку на новый лист в рабочей книге
LOCAL loSheet
loSheet = m.loBook.Sheets(1)

* Делаем Excel видимым
* Эту команду надо давать в самом конце формирования листа Excel
* здесь она приведена для наглядности
loExcel.Visible= .T.

Здесь сразу нужны некоторые пояснения.

Иерархия главных объектов Excel достаточно проста:

Сам объект Excel (Excel.Application) 
	Коллекция рабочих книг (WorkBooks) 
		Коллекция листов (Sheets) 
			Набор ячеек (Range, Cells, Columns, Rows)

Сам объект Excel (Excel.Application) - это некая "оболочка", которая сама по себе особого интереса не представляет. Ну, примерно как собственно среда FoxPro не имеет особого смысла без каких-то пользовательских форм или меню. Это просто "среда", где и "живут" все прочие объекты Excel

Коллекция рабочих книг (WorkBooks) - одна рабочая книга - это один файл XLS. Как правило, в одном объекте Excel открывается только один файл XLS (рабочая книга). Но, в принципе, можно открыть и несколько файлов XLS в одном объекте Excel.

Коллекция листов (Sheets) - один лист - это одна "страница" файла XLS. Или одна "сетка". При использованном выше способе создания рабочей книги будет создана рабочая книга только с одним листом. Если же вообще не указывать никаких параметров в методе Add при создании новой рабочей книги, то количество листов будет определяться настройками Excel у клиента. Пункт меню Excel с именем "Сервис" - "Параметры" - Закладка "Общие" - реквизит "Листов в новой книге"

Набор ячеек (Range, Cells, Columns, Rows) - это уже собственно ячейки листа Excel. Возможны разные способы адресации к ячейкам:

  • Range - произвольный набор ячеек, никак не связанных между собой. В частности, это может быть и одна ячейка, и строка, и столбец, и просто перечисление каких-либо ячеек
  • Cells - одна ячейка выделенного диапазона
  • Columns - один или несколько столбцов
  • Rows - одна или несколько строк

Чтобы начать заполнять лист Excel надо предварительно обязательно открыть сам объект Excel и в нем создать (или открыть) рабочую книгу.

Объект Excel создается именно командой CreateObject(), а не предварительной попыткой использовать уже существующий объект Excel через команду GetObject() не для наглядности. Именно так и следует поступать! Дело в том, что при использовании команды GetObject() неизвестно, какой именно из существующих объектов Excel будет "захвачен". Такая неопределенность рано или поздно, но "выйдет боком". Поэтому лучше создать новый объект и быть уверенным, что при этом никак не испортишь ранее открытые объекты Excel.

В приведенном выше примере я в конце концов получил ссылку на нужный мне лист Excel. Далее я буду работать именно с этой ссылкой. Однако, в принципе, вместо полной иерархии "Объект Excel - Рабочая книга - Лист - ячейка" можно работать и напрямую "Объект Excel - ячейка". Т.е. "пропустив" всю "лишнюю" иерархию "Рабочая книга - Лист".

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

Подключение механизма IntelliSens в FoxPro

Начиная с версии Visual FoxPro 7 появился механизм IntelliSens. Если у Вас младшая версия FoxPro, то данный раздел Вы можете смело пропустить. Для собственно перевода кода макроса Excel в синтаксис FoxPro то, что написано в данном разделе принципиального значения не имеет. Это просто дополнительные удобства, связанные исключительно с механизмом IntelliSens

Итак, механизм IntelliSens в частности отображает список всех свойств, методов и событий объекта в выпадающем списке, который появляется автоматически как только Вы установите точку сразу за именем объекта. Однако чтобы этот механизм сработал в программе необходимо выполнить то, что в FoxPro называется "ранее связывание". Другими словами, необходимо как-то дать понять FoxPro еще на этапе написания программного кода какой именно объект "скрывается" за выбранным именем переменной. Для этого используется специальный синтаксис в определении области видимости объекта. В данном случае, примерно так:

LOCAL loExcel as Excel.Application
loExcel=CREATEOBJECT('Excel.Application')

Откуда FoxPro узнал о том, где взять список свойств, событий и методов объекта Excel.Application? А из системного реестра Windows. Точнее, конечно, в системном реестре храниться не сам список свойств, а ссылка на библиотеку, в которой эти свойства описаны. Просто в процессе установки собственно Excel в системном реестре Windows был сформирован некий идентификатор для объекта с названием Excel.Application. А уже по этому идентификатору можно определить массу информации связанную с этим объектом. В том числе и полный путь к файлу со списком свойств и методов данного объекта.

Все это, конечно, хорошо. Но ведь основная работа будет происходить не собственно с объектом Excel.Application, а с объектами, существующими внутри Excel.Application. Неужели, для того, чтобы работал механизм IntelliSens придется всегда писать полную иерархию объектов Excel начиная с самого верхнего уровня?

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

В данном случае надо воспользоваться пунктом системного меню FoxPro с именем Tools - подпункт IntelliSens. В открывшемся окне перейдите на закладку Types и нажмите кнопку Type Libraries. Появится список тех объектов, которые зарегистрированы в системном реестре Windows. Вам следует найти в этом списке объект "Microsoft Excel 10.0 Obect Library". Или с большим номером. Библиотека с номером 5.0 нас не интересует, поскольку она не даст нужного результата.

Ставите птичку слева от имени "Microsoft Excel 10.0 Obect Library" и нажмите кнопку "Done". Это вовзвращает Вас в окно IntelliSens Meneger. Убедитесь, что в списке объектов в этом окне появилась только что выбраная Вами дополнительная библиотека, и нажмите кнопку "Ok"

Все. Теперь механизм IntelliSens будет работать не только для объекта, непосредственно зарегистрированного в системном реестре Windows, но и для "вложенных" в него объектов. Для этого, следует переписать приведенный выше код определения объектов следующим образом.


* Создаем объект Excel
LOCAL loExcel as Excel.Application
loExcel=CREATEOBJECT('Excel.Application')

* Создаем в нем новую рабочую книгу
LOCAL loBook as Excel.Workbook
#DEFINE xlWBATWorksheet -4167
loBook = m.loExcel.workbooks.Add(xlWBATWorksheet)

* Создаем ссылку на новый лист в рабочей книге
LOCAL loSheet as Excel.Worksheet
loSheet = m.loBook.Sheets(1)

* Делаем Excel видимым
* Эту команду надо давать в самом конце формирования листа Excel
* здесь она приведена для наглядности
loExcel.Visible= .T.

Метод Select

Первое, что бросается в глаза, при просмотре кода макроса Excel, это разбросанный по всему телу макроса метод Select. Что это такое? А это просто визуализация перехода или выделения нужной ячейки. Т.е. просто визуальное отображение того факта, что Вы встали, например, на ячейку "A1".

При написании кода в FoxPro нам это совсем не нужно. Ну, действительно, зачем нам показывать пользователю, что мы встали на ячейку "A1" и сейчас начнем в ней что-то менять?

Если сравнить с формами FoxPro, то метод Select в Excel аналогичен методу SetFocus() в FoxPro. А зачем нам переводить фокус, например, в TextBox, если я могу изменить его состояние и без этого? Достаточно просто получить ссылку на нужный объект. В данном случае на ячейку Excel.

Именно так и следует поступить. Тем более, что визуализация перехода на нужные ячейки занимает довольно значительное время. Тогда первая часть макроса - "заполнение ячеек" - в синтаксисе FoxPro с учетом предыдущего кода будет выглядеть так:


* Ввод содержимого ячеек
m.loSheet.Cells(1,1).Value = "Название реквизита"
m.loSheet.Cells(1,2).Value = "Значение реквизита"
m.loSheet.Cells(2,1).Value = "Первый"
m.loSheet.Cells(2,2).Value = 1324.56
m.loSheet.Cells(3,1).Value = "Второй"
m.loSheet.Cells(3,2).Value = "9876.54"
m.loSheet.Cells(4,1).Value = "ИТОГО"

В данном случае идет обращение к каждой отдельной ячейке. Поэтому для получения ссылки я использовал метод Cell(номер строки, номер столбца).

Откуда я взял синтаксис использования Cells()? Да из HELP самого Excel. Я просто в коде макроса выделил ключевое слово "Range" и нажал клавишу F1. Далее посмотрел пример его использования и увидел такой замечательный метод Cells() и пример его использования.

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

О ссылках на диапазон ячеек отличный от одной ячейки будет рассказано далее.

Указание диапазона ячеек для функции

По той же самой схеме, которая описана в предыдущем разделе, формулу для расчета итога можно записать так:


* Формула расчета итога
m.loSheet.Cells(4,2).Value = "=SUM(R[-2]C:R[-1]C)"
* Или в более привычном виде
m.loSheet.Cells(4,2).Formula = "=SUM(B2:B3)"

Однако оба этих способа имеют недостатки. Начну с конца, как более очевидного

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

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

R[-2]C

Следует читать как: строка (Row) на 2 выше от текущей и тот же самый, текущий, столбец (Column)

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

Немного покопавшись в HELP и поэкспериментировав, выяснилось, что можно писать не относительные ссылки, а абсолютные


* Формула расчета итога
m.loSheet.Cells(4,2).Formula = "=SUM(R2C2:R3C2)"
* Или несколько более громоздко
m.loSheet.Cells(4,2).Formula = "=SUM("+m.loSheet.Cells(2,2).Address +":"+m.loSheet.Cells(3,2).Address +")"

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

Использовать ли свойство Value или Formula в данном случае все равно. Оба свойства дадут один и тот же результат.

Обратите внимание еще на одну "тонкость". В данном случае использовано английское ключевое слово "SUM", несмотря на то, что я создал исходный макрос в русифицированной версии Excel. Т.е. если посмотреть, что же написано в самом листе Excel, то там будет стоять русское "СУММ".

Указание произвольного диапазона ячеек

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

Для указания произвольного диапазона ячеек используется метод Range(). В самом общем виде он имеет примерно такой синтаксис:

m.loSheet.Range("1:1;B:B;C2:D3")

В данном случае указан диапазон, в который входят: все ячейки первой строки, все ячейки столбца "B", все ячейки лежащие между ячейками "C2" и "D3". Т.е. символ двоеточия выступает как фраза "от ... до", а точка с запятой как фраза "... и ...".

Обратите внимание, что в коде макроса Excel вместо символа точки с запятой использован символ запятой. Это не опечатка. Это отличие синтаксиса внутри Excel и при работе с самим Excel как COM-компонентом. О том, когда надо использовать "точку с запятой", а когда просто "запятую" чуть ниже.

Внутри метода RANGE недопустимо использование абсолютных ссылок вида "R1C1", как это можно сделать внутри формул. Это вызовет ошибку. Следовательно, по сути, единственным способом указания произвольного диапазона остается считывание нужных адресов. Если взять приведенный выше пример, то получается так:

m.loSheet.Range(m.loSheet.Rows(1).Address+";"+;
	m.loSheet.Columns(2).Address+";"+;
	m.loSheet.Cells(3,2).Address+":"+m.loSheet.Cells(4,3).Address)

Ну, а фрагмент кода макроса переводится в синтаксис FoxPro следующим образом:

m.loSheet.Range(m.loSheet.Rows(1).Address+";"+;
	m.loSheet.Columns(4).Address).Font.Bold = .T.

Следует заметить, что писать в одном методе RANGE() слишком уж длинных строк диапазонов не надо. Дело в том, что у команд Excel, также как и у команд FoxPro, есть ограничение по длине. В данном случае - это вероятно 1024 символа на одну команду. Если Вы хотите одной командой изменить множество разрозненных ячеек, то следует их объединить при помощи метода Union. Примерно так:

LOCAL loUnion
loUnion = m.loExcel.UNION(m.loSheet.Rows(1),m.loSheet.Rows(2))
loUnion = m.loExcel.UNION(m.loUnion,m.loSheet.Cells(3,2))
loUnion = m.loExcel.UNION(m.loUnion,m.loSheet.Cells(3,3))
loUnion = m.loExcel.UNION(m.loUnion,m.loSheet.Cells(4,2))
loUnion = m.loExcel.UNION(m.loUnion,m.loSheet.Cells(4,3))
m.loUnion.Font.Bold = .T.

Обратите внимание, что метод UNION относиться к объекту "Excel.Application" (переменная m.loExcel). Это значит, что в нем можно объединять диапазоны не просто из разных листов, но и из разных книг.

Метод UNION не может иметь меньше двух параметров. Однако нельзя одной командой указать больше 30 параметров. Впрочем, как видно из примера, можно наращивать уже объединенные ячейки. Т.е. в качестве первого параметра указать ранее объединенный через UNION диапазон ячеек.

Использование метода UNION - это еще один способ указания произвольного диапазона

Когда использовать "запятую", а когда "точку с запятой

При переводе кода макроса Excel в синтаксис FoxPro иногда приходится заменять символ "запятой" на символ "точки с запятой" и наоборот. С чем это связано, и когда это необходимо делать?

Это связано с особенностью разделения параметров в синтаксисе Visual Basic и в синтаксисе FoxPro. Чтобы не залезать глубоко в "дебри" мудреных определений просто запомните общее правило:

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

Чтобы было понятно о чем речь, возьмем ранее рассмотренный пример выделения диапазона ячеек. В макросе Excel это записано так:

Range("1:1,4:4").Select

Здесь, по смыслу, внутри Range() просто перечислены элементы одного списка. Если "перевести" это на русский язык, то можно прочитать это так: выделить первую и четвертую строку

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

m.loSheet.Range("1:1;4:4").Select

К сожалению, в использованном в качестве примера коде макроса нет функций, которые бы использовали диапазоны как параметры. Поэтому приведу пример функции ЕСЛИ() никакого отношения к разбираемому коду макроса не имеющую.

.ActiveCell.FormulaR1C1 = '=IF(RC[-1]>0;RC[-1];"")'

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

Как видите, в коде макроса использован символ "точки с запятой". Но в данном случае, разделенные величины выступают как параметры. Это явно не перечисление. Значит, в синтаксисе FoxPro следует вместо символа "точки с запятой" использовать символ "запятой".

m.loSheet.Cells(2,3).Value = '=IF(RC[-1]>0,RC[-1],"")'

Указание формата ячеек

Далее в коде макроса стоит указание формата для всего второго столбца. В переводе в синтаксис FoxPro это выглядит так:

m.loSheet.Columns(2).NumberFormat = "#,##0.00"

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

В данном случае символ запятой и точки - это не есть реальные символы-разделители. Их назначение аналогично назначению тех же символов при задании маски ввод "InputMask" в FoxPro.

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

Например, если Вы выводите в Excel банковский расчетный счет (это 20 цифр), то Excel автоматически конвертирует полученное значение в число. Но, поскольку точность вычисления Excel до 15 значащих цифр, то произойдет округление и последующее изменение формата отображения уже не сможет исправить эту ошибку.

В подобных случаях надо до начала вывода в Excel установить формат ячеек - текстовый

m.loSheet.Columns(1).NumberFormat = "@"

Установка условного формата для числовых данных второго столбца

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

Константы Excel

В теле макроса встречаются странные значения, которые начинаются с символов "xl". В данном случае - это xlCellValue и xlLess. Но и дальше по коду макроса встречаются аналогичные значения. Это именно значения, поскольку, судя по коду, они присваиваются неким параметрам. Что это такое?

Это константы. Т.е. это некоторые значения, которые были определены в момент открытия Excel. Их отличительным признаком как раз и является то, что они начинаются с символов "xl" и из кода макроса следует, что это некоторые ранее определенные значения.

Определить, чему же равны эти константы можно там же, в редакторе "Microsoft Visula Basic", где Вы и просматриваете код макроса Excel. Для этого надо открыть "Object Browser". Пункт меню "View" - подпункт "Object Browser". Далее в пустом окошке слева от кнопки с иконкой бинокля ввести имя искомой константы и нажать кнопку с иконкой бинокля (или клавишу Enter). В результате поиска в самом низу окна "Object Browser" будет отображено значение искомой константы.

В синтаксисе FoxPro константы записываются через директиву #DEFINE следующим образом:

#DEFINE xlCellValue 1
#DEFINE xlLess 6

Именованные параметры функций Excel

В коде макроса, для установки условного формата используется функция ADD с несколькими именованными параметрами. Как это перевести в синтаксис FoxPro, ведь в нем нет такого понятия как "именованный параметр"

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

Повторю еще раз. Такого в FoxPro нет. Т.е. реализовать-то это не проблема. Просто этого нет "штатно". На уровне самой среды FoxPro.

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

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

Тогда все очень просто. В FoxPro установка условного форматирования примет вид


#DEFINE xlCellValue 1
#DEFINE xlLess 6
LOCAL loUnion, loFormatCondition
loUnion = m.loExcel.Union(m.loSheet.Cells(2,2),m.loSheet.Cells(3,2))
loUnion = m.loExcel.Union(m.loUnion,m.loSheet.Cells(4,2))
m.loUnion.FormatConditions.Delete
loFormatCondition = m.loUnion.FormatConditions.Add(xlCellValue,xlLess,2000)
m.loFormatCondition.Interior.ColorIndex = 3

В данном случае, все параметры метода Add() обязательны. Т.е. нельзя не задать какой-либо из параметров. Однако во многих функциях часть параметров задавать не обязательно. Это означает либо что данный параметр остается неизменным, либо принимает некоторое значение по умолчанию. В этом случае в синтаксисе FoxPro можно просто ничего не указывать, но обязательно поставить запятую, чтобы нужный нам параметр оказался на соответствующем месте.

Рисование рамки вокруг всех данных

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


#DEFINE xlThin 2
#DEFINE xlDiagonalDown 5
#DEFINE xlDiagonalUp 6
#DEFINE xlEdgeLeft 7
#DEFINE xlEdgeTop 8
#DEFINE xlEdgeBottom 9
#DEFINE xlEdgeRight 10
#DEFINE xlInsideVertical 11
#DEFINE xlInsideHorizontal 12

LOCAL loRange
loRange = m.loSheet.Range(m.loSheet.Cells(1,1).Address+":"+m.loSheet.Cells(4,2).Address)
loRange.Borders(xlEdgeLeft).Weight = xlThin
loRange.Borders(xlEdgeTop).Weight = xlThin
loRange.Borders(xlEdgeBottom).Weight = xlThin
loRange.Borders(xlEdgeRight).Weight = xlThin
loRange.Borders(xlInsideVertical).Weight = xlThin
loRange.Borders(xlInsideHorizontal).Weight = xlThin

Как видите, большая часть кода просто не вошла в итоговый "перевод". В этом нет необходимости. В данном случае нас вполне устраивает стиль и цвет линий по умолчанию. Т.е. сплошная линия черного цвета. Нет смысла менять эти значения. Достаточно только указания толщины (веса) линии

Перенос слов, выравнивание, ширина столбца и высота строки

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


#DEFINE xlCenter -4108
#DEFINE xlTop -4160

m.loSheet.Rows(1).NumberFormat = "@"
m.loSheet.Rows(1).HorizontalAlignment = xlCenter
m.loSheet.Rows(1).VerticalAlignment = xlTop
m.loSheet.Rows(1).WrapText = .T.
m.loSheet.Rows(1).RowHeight = 25.5

m.loSheet.Columns(1).ColumnWidth = 11.57
m.loSheet.Columns(2).ColumnWidth = 10.14
0

Автор публикации

не в сети 24 года

Владимир Максимов

0
Комментарии: 0Публикации: 63Регистрация: 02-09-2000
Оставить комментарий
Авторизация
*
*
Генерация пароля