Source: Microsoft Support
RAPID PUBLISHING
RAPID PUBLISHING ARTICLES PROVIDE INFORMATION DIRECTLY FROM WITHIN THE MICROSOFT SUPPORT ORGANIZATION. THE INFORMATION CONTAINED HEREIN IS CREATED IN RESPONSE TO EMERGING OR UNIQUE TOPICS, OR IS INTENDED SUPPLEMENT OTHER KNOWLEDGE BASE INFORMATION.
Action
You have a Microsoft Excel 2007 workbook (.XLSX). You want to import data from it into a Microsoft Visual FoxPro (VFP) table using VFP.
Resolution
There are a number of ways of accomplishing this task:
1. Export the Excel sheet(s) as comma delimited files (.CSV) and use the IMPORT command or the Import Wizard inside VFP to import the file(s).
2. Write custom VFP OLE automation code to automate Excel and extract the data to VFP.
3. Use the Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb) ODBC driver included with the 2007 Office System Driver: Data Connectivity Components package to access and extract data from the Excel workbook, either through a VFP Remote View or programmatically, as in the following sample code:
*————————————
* AUTHOR: Trevor Hancock
* CREATED: 02/15/08 04:55:31 PM
* ABSTRACT: Code demonstrates how to connect to
* and extract data from an Excel 2007 Workbook
* using the «Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)»
* from the 2007 Office System Driver: Data Connectivity Components
*————————————
LOCAL lcXLBook AS STRING, lnSQLHand AS INTEGER, ;
lcSQLCmd AS STRING, lnSuccess AS INTEGER, ;
lcConnstr AS STRING
CLEAR
lcXLBook = [C:SampleWorkbook.xlsx]
lcConnstr = [Driver=] + ;
[{Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};] + ;
[DBQ=] + lcXLBook
IF !FILE( lcXLBook )
? [Excel file not found]
RETURN .F.
ENDIF
*— Attempt a connection to the .XLSX WorkBook.
*— NOTE: If the specified workbook is not found,
*— it will be created by this driver! You cannot rely on a
*— connection failure — it will never fail. Ergo, success
*— is not checked here. Used FILE() instead.
lnSQLHand = SQLSTRINGCONNECT( lcConnstr )
*— Connect successful if we are here. Extract data…
lcSQLCmd = [Select * FROM «Sheet1$»]
lnSuccess = SQLEXEC( lnSQLHand, lcSQLCmd, [xlResults] )
? [SQL Cmd Success:], IIF( lnSuccess > 0, ‘Good!’, ‘Failed’ )
IF lnSuccess < 0
LOCAL ARRAY laErr[1]
AERROR( laErr )
? laErr(3)
SQLDISCONNECT( lnSQLHand )
RETURN .F.
ENDIF
*— Show the results
SELECT xlResults
BROWSE NOWAIT
SQLDISCONNECT( lnSQLHand )
DISCLAIMER
MICROSOFT AND/OR ITS SUPPLIERS MAKE NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY, RELIABILITY OR ACCURACY OF THE INFORMATION CONTAINED IN THE DOCUMENTS AND RELATED GRAPHICS PUBLISHED ON THIS WEBSITE (THE “MATERIALS”) FOR ANY PURPOSE. THE MATERIALS MAY INCLUDE TECHNICAL INACCURACIES OR TYPOGRAPHICAL ERRORS AND MAY BE REVISED AT ANY TIME WITHOUT NOTICE.
TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, MICROSOFT AND/OR ITS SUPPLIERS DISCLAIM AND EXCLUDE ALL REPRESENTATIONS, WARRANTIES, AND CONDITIONS WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED TO REPRESENTATIONS, WARRANTIES, OR CONDITIONS OF TITLE, NON INFRINGEMENT, SATISFACTORY CONDITION OR QUALITY, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, WITH RESPECT TO THE MATERIALS.
Need more help?
Want more options?
Explore subscription benefits, browse training courses, learn how to secure your device, and more.
Communities help you ask and answer questions, give feedback, and hear from experts with rich knowledge.
- Исходный макрос 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
- Remove From My Forums
-
Вопрос
-
I am using Visual FoxPro 6.0 version. I need an excel file just view in Visual FoxPro 6.0 form… Please send the code and proceedures….
Ответы
-
I’d never do that myself and show it in Excel’s own application window. However if you’d do anyway:
Code Snippet
lcXLSFile = getFile(‘XLS’)
PUBLIC oForm
oForm = createobject(‘myExcelForm’,m.lcXLSFile)
oForm.show()define class myExcelForm as form
top = 0
left = 0
height = 450
width = 750
docreate = .t.
caption = «HTML Excel sample»* This is IE control — you’d use webbrowser4 from gallery instead
* just because it already has some checks, extra pem. ie: wouldn’t need readystate part
* for the sake of keeping code short here I directly use olecontrol itself
add object htmlviewer as olecontrol with ;
top = 0, ;
left = 0, ;
height = 450, ;
width = 750, ;
visible = .t., ;
name = «HTMLViewer», ;
oleclass = ‘Shell.Explorer’procedure init
lparameters tcXLSFile
with thisform.htmlviewer
.Navigate2(‘file://’+m.tcXLSFile)
do while .ReadyState # 4 && Wait for ready state
enddo
endwith
endproc
enddefineInstead of web browser you might directly use an place editing window too. It’s however is much worse and here is why:
Code Snippet
lcXLS = Getfile(‘XLS’)
Set Textmerge To Memvar myVar Noshow
Set Textmerge On
DEFINE CLASS oleExcelObject as OLEControl
OleClass =»Excel.Sheet» && Server name
OleTypeAllowed = 0 && Linked
DocumentFile = «<<m.lcXLS>>» && This file should exist
ENDDEFINE
Set Textmerge To
Set Textmerge Off
lcTempClass = Sys(2015)+’.prg’
Strtofile(myVar, lcTempClass)
Compile (lcTempClass)PUBLIC oForm
oform = Createobject(«Form»)
oForm.Show()With oform
.Height = 420
.Width = 620
.Newobject(«ExcelObject»,»oleExcelObject»,lcTempClass) && Add OLE object
With .ExcelObject
.Left = 5
.Top = 5
.Width = .Parent.Width — 10
.Height = .Parent.Height — 10
.Visible = .T.
Endwith
Endwith
oform.Show
Read Events
Clear Class ‘oleExcelObject’
Erase (Juststem(m.lcTempClass)+’.*’) -
In addition to Cetin’s reply there is another interesting idea (in this sample I use Word, though)
DECLARE SetParent IN user32 integer hWndChild, integer hWndParent DECLARE integer SetWindowPos IN User32 ; integer Wnd_handler, integer Window_Order, ; integer X1, integer Y1, integer X2, integer Y2, integer wFlags DECLARE LONG FindWindow IN Win32API ; STRING lpClassName; ,STRING lpWindowName loWord = CREATEOBJECT( 'WORD.APPLICATION') lcFile = GETFILE('doc') loDoc=m.loWord.Documents.Add(m.lcFile) _PP=lodoc.name +" - "+loword.CAPTION word_hwnd=FindWindow(NULL,_pp) SetParent( word_hwnd, thisform.HWnd) setWindowPos( word_hwnd,0,0,INT(THISFORM.Height/2),THISFORM.Width-1,THISFORM.HEIGHT-1,0) loword.ActiveWindow.ActivePane.View.Zoom.PageFit = 1 loword.VISIBLE=.T.
У меня данный способ заработал. Вы сами не знаете какой именно файл
Предлагаю вам создать в Visual Foxpro 9 новый файл данных, занести туда пару строк и продемонстрировать работу вашего способа.
Если у вас нет Visual Foxpro 9 — то могу сам вам создать данный файл данных (если вы согласны скачать с темы «неизвестное» вложение), а вы на нём продемонстрируете, как это работает на практике.
Скриншотами с Excel.
Складывается ощущения, что вы считаете себя самым умным, а остальные ****
У вас складывается неверное ощущение.
Я просто привык проверять ответы на задачи, с которыми я сталкивался раньше на практике, и если они неверны — информировать об этом собеседника. Считайте это дружеской помощью, а не попыткой троллить.
Если я, к примеру, буду давать неверные ответы по настройкам KIS 2016, а в ответ на поправки форумчан, аргументировать, показать это я не могу, т.к. у меня нет на компьютере KIS 2016 и я им вообще не пользуюсь, но это всё равно должно быть так, то вот это уже будет троллингом.
Вероятно нужно промолчать по вашим сообщениям, если это как то задевает вашу самооценку. Не буду даже снижать вам репутацию за неверные ответы, как это принято на форумах.
Как было правильно замечено:
Какая вам разница — признаю я ваш вариант истинным или нет
Изменено 11 декабря, 2015 пользователем Turkoman
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 |
#Define xlCenter -4108 #Define xlSolid 1 #Define xlEdgeLeft 7 #Define xlEdgeTop 8 #Define xlEdgeBottom 9 #Define xlEdgeRight 10 #Define xlInsideVertical 11 #Define xlInsideHorizontal 12 #Define xlThin 2 #Define xlThick 4 #Define xlMedium -4138 #Define xlDouble -4119 Local lcPath, loExcel, lnRow loExcel = Createobject("Excel.Application") With loExcel .Visible = .T. .WorkBooks.Add **.ActiveWindow.DisplayZeros = .F. * Устанавлиаем ширину столбцов .Columns[1].ColumnWidth = 5 .Columns[2].ColumnWidth = 40 .Columns[3].ColumnWidth = 10.71 .Columns[4].ColumnWidth = 15 .Columns[5].ColumnWidth = 15 .Columns[6].ColumnWidth = 15 .Columns[7].ColumnWidth = 15 .Columns[8].ColumnWidth = 15 .Columns[9].ColumnWidth = 15 * Заголовок .cells(1,3).Font.Size = 13 .cells(1,3).Font.Bold = .T. .cells(1,3).Value = 'Накопительная ведомость данных путевых листов по автомобилям' .cells(2,5).Font.Size = 11 .cells(2,5).Font.Bold = .F. .Range("A7:I7").Select .ActiveWindow.FreezePanes = .T. With .Selection .RowHeight = 18 .Font.Size = 10 .Font.Bold = .T. Endwith .cells(5,1).Value = '№ пп' .cells(5,2).Value = 'Наименование автомобиля, номер и дата путевого листа' .cells(5,3).Value = 'Единица измерения' .cells(5,4).Value = 'Остаток на начало отчетного периода' .cells(5,5).Value = 'Поступило' .cells(5,6).Value = 'Расход ' .cells(5,7).Value = 'Остаток на конец отчетного периода' .cells(5,8).Value = 'Показания спидометра на' .cells(6,8).Value = 'начало отчетного периода' .cells(6,9).Value = 'конец отчетного периода' *редактируем ячейки для дальнейшего использования .Range("A5:A6").Select With .Selection .MergeCells = .T. .HorizontalAlignment = xlCenter .VerticalAlignment = xlCenter .WrapText = .T. .Orientation = 0 .AddIndent = .F. .IndentLevel = 0 .ShrinkToFit = .F. .ReadingOrder = -5002 &&xlContext Endwith .Range("B5:B6").Select With .Selection .MergeCells = .T. .HorizontalAlignment = xlCenter .VerticalAlignment = xlCenter .WrapText = .T. .Orientation = 0 .AddIndent = .F. .IndentLevel = 0 .ShrinkToFit = .F. .ReadingOrder = -5002 Endwith .Range("C5:C6").Select With .Selection .MergeCells = .T. .HorizontalAlignment = xlCenter .VerticalAlignment = xlCenter .WrapText = .T. .Orientation = 0 .AddIndent = .F. .IndentLevel = 0 .ShrinkToFit = .F. .ReadingOrder = -5002 Endwith .Range("D56").Select With .Selection .MergeCells = .T. .HorizontalAlignment = xlCenter .VerticalAlignment = xlCenter .WrapText = .T. .Orientation = 0 .AddIndent = .F. .IndentLevel = 0 .ShrinkToFit = .F. .ReadingOrder = -5002 Endwith .Range("E5:E6").Select With .Selection .MergeCells = .T. .HorizontalAlignment = xlCenter .VerticalAlignment = xlCenter Endwith .Range("F5:F6").Select With .Selection .MergeCells = .T. .HorizontalAlignment = xlCenter .VerticalAlignment = xlCenter Endwith .Range("G5:G6").Select With .Selection .MergeCells = .T. .HorizontalAlignment = xlCenter .VerticalAlignment = xlCenter .WrapText = .T. .Orientation = 0 .AddIndent = .F. .IndentLevel = 0 .ShrinkToFit = .F. .ReadingOrder = -5002 Endwith .Range("H5:I5").Select With .Selection .MergeCells = .T. .HorizontalAlignment = xlCenter .VerticalAlignment = xlCenter Endwith .Range("H6:H6").Select With .Selection .MergeCells = .T. .HorizontalAlignment = xlCenter .VerticalAlignment = xlCenter .WrapText = .T. .Orientation = 0 .AddIndent = .F. .IndentLevel = 0 .ShrinkToFit = .F. .ReadingOrder = -5002 Endwith .Range("I6:I6").Select With .Selection .MergeCells = .T. .HorizontalAlignment = xlCenter .VerticalAlignment = xlCenter .WrapText = .T. .Orientation = 0 .AddIndent = .F. .IndentLevel = 0 .ShrinkToFit = .F. .ReadingOrder = -5002 Endwith .Range("A5:I6").Select With .Selection .BorderS(xlEdgeLeft).Weight = xlMedium .BorderS(xlEdgeTop).Weight = xlMedium .BorderS(xlEdgeBottom).Weight = xlMedium .BorderS(xlEdgeRight).Weight = xlMedium .BorderS(xlInsideVertical).Weight = xlThin .BorderS(xlInsideHorizontal).Weight = xlThin .HorizontalAlignment = xlCenter .VerticalAlignment = xlCenter Endwith .Rows("6:6").RowHeight = 45 .cells(7,1).NumberFormat = "@" .cells(7,1).Value = "1" .cells(7,2).NumberFormat = "@" .cells(7,2).Value = "2" .cells(7,3).NumberFormat = "@" .cells(7,3).Value = "3" .cells(7,4).NumberFormat = "@" .cells(7,4).Value = "4" .cells(7,5).NumberFormat = "@" .cells(7,5).Value = "5" .cells(7,6).NumberFormat = "@" .cells(7,6).Value = "6" .cells(7,7).NumberFormat = "@" .cells(7,7).Value = "7" .cells(7,8).NumberFormat = "@" .cells(7,8).Value = "8" .cells(7,9).NumberFormat = "@" .cells(7,9).Value = "9" *делаем сквозную строку With .ActiveSheet.PageSetup .PrintTitleRows = "$7:$7" .PrintTitleColumns = "" EndWith .Range("A7:I7").Select With .Selection .BorderS(xlEdgeLeft).Weight = xlMedium .BorderS(xlEdgeTop).Weight = xlMedium .BorderS(xlEdgeBottom).Weight = xlMedium .BorderS(xlEdgeRight).Weight = xlMedium .BorderS(xlInsideVertical).Weight = xlThin .BorderS(xlInsideHorizontal).Weight = xlThin .HorizontalAlignment = xlCenter .VerticalAlignment = xlCenter Endwith lnRow = 7 *тут заполняем таблицу своими данными .Range(.cells(8,1),.cells(lnRow, 9)).Select With .Selection .BorderS(xlEdgeLeft).Weight = xlMedium .BorderS(xlEdgeTop).Weight = xlMedium .BorderS(xlEdgeBottom).Weight = xlMedium .BorderS(xlEdgeRight).Weight = xlMedium .BorderS(xlInsideVertical).Weight = xlThin .BorderS(xlInsideHorizontal).Weight = xlThin .HorizontalAlignment = xlCenter .VerticalAlignment = xlCenter Endwith lnRow = lnRow + 2 .cells(lnRow,2).NumberFormat = "@" .cells(lnRow,2).Value = "Отчет проверил _______________________________________________________________________" Endwith Messagebox ('Данные выгружены в программу Excel',0+48,; 'Сообщение программы') |