Delphi excel formula if

Содержание

  1. Excel delphi формула если
  2. Excel delphi формула если
  3. Excel delphi формула если

Excel delphi формула если

формула в ячейку Excel помещается так:

вопрос в том, как заставить Excel ее вычислить, потому как вместо результата в ячейке светится #ИМЯ? и подсказка «формула содержит нераспознанный текст» и если после этого установить курсор на строку с форулой и просто нажать Enter то формула прекрасно вычисляется. Как сделать то же самое программным методом?
причем строка «=(2+2)» вычисляется нормально.
насколько я понял распознать оно не может слово «СУММ».
также пытался делать нечто вроде

но это ничего не меняет.

От: Horror_Infinity
Дата: 18.10.05 12:07
Оценка:

Здравствуйте, A7exander, Вы писали:

A>формула в ячейку Excel помещается так:
A>

A> вопрос в том, как заставить Excel ее вычислить, потому как вместо результата в ячейке светится #ИМЯ? и подсказка «формула содержит нераспознанный текст» и если после этого установить курсор на строку с форулой и просто нажать Enter то формула прекрасно вычисляется. Как сделать то же самое программным методом?
A> причем строка «=(2+2)» вычисляется нормально.
A> насколько я понял распознать оно не может слово «СУММ».
A> также пытался делать нечто вроде
A>
A>но это ничего не меняет.

Правильно будет написать вот так:

Имена формул надо писать по-английски. И будет тебе счастье. Причем, неважно — русский или аглицкий ексель у тебя стоит.

От: Danchik
Дата: 18.10.05 12:13
Оценка:

Здравствуйте, A7exander, Вы писали:

Попробуй написать так:

От: A7exander
Дата: 18.10.05 12:34
Оценка:

Здравствуйте, Horror_Infinity, Вы писали:

H_I>Правильно будет написать вот так:
H_I>
H_I>Имена формул надо писать по-английски. И будет тебе счастье. Причем, неважно — русский или аглицкий ексель у тебя стоит.

Спасибо за отклик, попробовал, но в результате тот же «#ИМЯ?» вместо результата, та же подсказка, но вдобавок теперь если установить курсор на строку с формулой в ячейке и нажать Enter то ничего не меняется, тоесть похоже «SUMM» эксель не понимает впринципе. Может где то переключить что нибудь нужно, чтоб англоязычные функции понимал? Эксель из пакета «OFFICE 2003»

От: A7exander
Дата: 18.10.05 12:41
Оценка:

Здравствуйте, Danchik, Вы писали:

D>Попробуй написать так:
D>

Как я уже отвечал Horror_Infinity, применение «SUMM» ничего не дает, и Excel понимает только «СУММА». Применение «.Formula» к сожалению таже ничего не меняет.

От: Horror_Infinity
Дата: 18.10.05 12:51
Оценка:

Здравствуйте, A7exander, Вы писали:

H_I>>
A>Спасибо за отклик, попробовал, но в результате тот же «#ИМЯ?» вместо результата, та же подсказка, но вдобавок теперь если установить курсор на строку с формулой в ячейке и нажать Enter то ничего не меняется, тоесть похоже «SUMM» эксель не понимает впринципе. Может где то переключить что нибудь нужно, чтоб англоязычные функции понимал? Эксель из пакета «OFFICE 2003»

Сорри за опечатку!
Конечно же, надо написать вот так:

З.Ы. На будущее. Очень легко подсмотреть, как правильно писать формулы: Включаешь запись макроса в Екселе, пишешь нужную тебе формулу, останавливаешь запись, идешь в редактор макросов и смотришь, как надо тебе в дельфе написать, чтоб все работало.

От: Dimonka
Дата: 18.10.05 12:59
Оценка:
От: A7exander
Дата: 18.10.05 13:17
Оценка:

Здравствуйте, Horror_Infinity, Вы писали:

H_I>Сорри за опечатку!
H_I>Конечно же, надо написать вот так:
H_I>

H_I>З.Ы. На будущее. Очень легко подсмотреть, как правильно писать формулы: Включаешь запись макроса в Екселе, пишешь нужную тебе формулу, останавливаешь запись, идешь в редактор макросов и смотришь, как надо тебе в дельфе написать, чтоб все работало.

Спасибо, SUM сработало, причем если SUM набирать в формуле вручную то Excel ее не понимает, что меня и сбило с толку, однако при программном занесении в ячейку конвертирует в «СУММ» и нормально вычисляет.

От: A7exander
Дата: 18.10.05 13:17
Оценка:

Спасибо, применение «SUM» помогло

От: NRiS
Дата: 18.10.05 17:14
Оценка:

что бы эксель понимал формулы с кирилическими символами вроде СУММ нодо писать так

От: Horror_Infinity
Дата: 19.10.05 04:40
Оценка:

Здравствуйте, NRiS, Вы писали:

NRS>что бы эксель понимал формулы с кирилическими символами вроде СУММ нодо писать так

Тогда английский ексель перестает понимать такие формулы. Как быть? У меня (да и не только у меня) стоит именно оригинальная английская версия.

Источник

Excel delphi формула если

Добрцый день! Есть такая проблема: хочется из Delphi 5 записывать в MS Excel всякие разные формулы, отличные от SUM. Помогите кто знает как это делать!


Романов Р.В. ( 2004-01-08 12:25 ) [1]


REP ( 2004-01-08 12:31 ) [2]

cells.Formula := «=MIN(A1:A10)»; Вроде как русские формулы он не понимает. Хотя может и от версии зависит.


EgorT ( 2004-01-08 12:34 ) [3]

Не помогает пишет «#ИМЯ?» в той ячейке, то есть результат считать не могу, или если записть формулу «=ЕСЛИ(A1=10;A2+A3;0)» тоже ничего хорошего не получилось


EgorT ( 2004-01-08 12:35 ) [4]

например Сумм понимает замечательно а все остальное нет

A1 пиши на английской раскладке


REP ( 2004-01-08 13:06 ) [6]

Вместо точки с запятой используй ЗАПЯТУЮ
А в сумм ты не используешь точку с запятой
Типа:
«=ЕСЛИ(A1=10 , A2+A3,0)»


EgorT ( 2004-01-08 13:10 ) [7]

А1 пишу по английски, а на счет запятой попробую


Карелин Артем ( 2004-01-08 13:26 ) [8]

Делай макрос и формулу бери из макроса. К примеру =ЕСЛИ(H8=12;G3;12) на самом деле будет «=IF(R[7]C[7]=12,R[2]C[6],12)»


EgorT ( 2004-01-08 13:39 ) [9]

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

Карелин Артем © (08.01.04 13:26) [8]
Ну не обязательно уж прямо R[7]C[7] Можно и обычно использовать H8, однако с синтаксисом нужно быть поосторожнее. Можно в Екселе находить нужную формулу по русски, а затем в «смотри также»(See also) находить ее англоязычный синтаксис


Карелин Артем ( 2004-01-08 13:52 ) [11]

REP © (08.01.04 13:45) [10]
Не обязательно. Это я через запись макроса получил.
EgorT (08.01.04 13:39) [9]
Именно не понял идею. Через макрос Названия формул надо получать. Хранить из не надо.


REP ( 2004-01-08 14:03 ) [12]

Карелин Артем © (08.01.04 13:52) [11]
Сидим и говорим друг другу «не обязательно, не обязательно»
Все таки нагляднее H8 (роднее для тех кто ексель знает немного)
А так пиши как угодно, не спорю.
:))

EgorT (08.01.04 13:39) [9]
А идея рассмотрена в соседней ветке:
http://delphimaster.net/view/1-1073549258/

По сути однотипные вопросы-то. И решение проблемы одно.

Источник

Excel delphi формула если

В этой статье я познакомлю вас как работать с MS Excel из Delphi. Данная статья может быть полезна людям, которые хотят научиться создавать различные отчеты в Excel из программ написанных на Delphi. Статья содержит справочные данные необходимые для работы с MS Excel. Здесь вы найдете информацию о том как:

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

Работать будем через модуль ComObj, для этого в uses необходимо добавить модуль ComObj и модуль Excel_TLB (для MS Excel 2007).

Uses ……, ComObj, Excel_TLB;

Модуль Excel_TLB содержит необходимые константы для работы с Excel, его можно не подключать, но тогда придется в ручную прописывать значения всех используемых констант из этого модуля. Значения констант можно найти внутри модуля или в интернете, но для разных версий MS Excel они разные.
Внимание. Модуль Excel_TLB в других версиях MS Excel может называться по другому. Перед подключением модуля Excel_TLB, необходимо импортировать библиотеку Excel. Для этого выберите Component->Import Component->Import a Type Library-> находим MS Excel и следуем инструкциям.

В разделе описания переменных мы должны описать переменную типа Variant или OleVariant для подключения интерфейса Excel. Я описал переменную excel.

Form1: TForm1;
excel : variant; // Переменная в которой создаётся объект EXCEL

Внимание. Всегда когда создаете объект интерфейса, заключайте процедуру создания в модуль обработки ошибок:
try
создаем интерфейс;
формируем отчет;
освобождаем интерфейс;
Except
обрабатываем ошибки;
освобождаем интерфейс;
end;

Далее идет краткий справочник по основным функциям работы с EXCEL

try
// создаем обьект EXCEL
excel := CreateOleObject(‘Excel.Application’);

// Чтоб не задавал вопрос о сохранении документа
excel.DisplayAlerts := false;

// создаем новый документ рабочую книгу
excel.WorkBooks.Add;

// или загружаем его из директории с программой
excel.WorkBooks.Open(GetCurrentDir() + ‘отчет.xls’);

// Делаем его видимым данную функцию после отладки и тестирования лучше использовать в конце, после сформирования отчета (это ускоряет процесс вывода данных в отчет)
excel.Visible := true;

//задаем тип формул в формате R1C1
excel.Application.ReferenceStyle := xlR1C1;

// задаем тип формул в формате A1
excel.Application.ReferenceStyle := xlA1;

// Задаем название первому и второму листу
excel.WorkBooks[1].WorkSheets[1].Name := ‘Отчет1’;
excel.WorkBooks[1].WorkSheets[2].Name := ‘Отчет2’;

//задаем формат числа для первой и четвертой колонки формат числа
excel.WorkBooks[1].WorkSheets[1].Columns[1].NumberFormat := ‘0,00’;
excel.WorkBooks[1].WorkSheets[1].Columns[4].NumberFormat := ‘0,0’;

// задаем ширину первой и второй колонки
excel.WorkBooks[1].WorkSheets[1].Columns[1].ColumnWidth := 10;
excel.WorkBooks[1].WorkSheets[1].Columns[2].ColumnWidth := 20;

// задаем начертание, цвет, размер и тип шрифта для первого ряда
excel.WorkBooks[1].WorkSheets[1].Rows[1].Font.Bold := True; //жирный
excel.WorkBooks[1].WorkSheets[1].Rows[1].Font.Color := clRed; // цвет красный
excel.WorkBooks[1].WorkSheets[1].Rows[1].Font.Size := 12; //размер 12
excel.WorkBooks[1].WorkSheets[1].Rows[1].Font.Name := ‘Times New Roman’; //шрифт

//присваиваем ячейке 1,4 и 2,4 значения (1 — ряд, 4 — колонка)
excel.WorkBooks[1].WorkSheets[1].Cells[1, 4] := ‘А так можно внести значение в ячейку’;
excel.WorkBooks[1].WorkSheets[1].Cells[2, 4] := ‘А так можно внести значение в ячейку’;

//ввод в ячейку ‘A12’ формулы ‘=b5+c4’
excel.WorkBooks[1].WorkSheets[1].Range[‘A12′].Formula:=’=b5+c4’;

// Выравнивам первый ряд по центру по вертикали
excel.WorkBooks[1].WorkSheets[1].Rows[1].VerticalAlignment := xlCenter;

// Выравнивам первый ряд по центру по горизонтали
excel.WorkBooks[1].WorkSheets[1].Rows[1].HorizontalAlignment := xlCenter;

// Выравнивам в ячейке по левому краю
excel.WorkBooks[1].WorkSheets[1].Cells[3, 2].HorizontalAlignment := xlLeft;

// Выравнивам в ячейке по правому краю
excel.WorkBooks[1].WorkSheets[1].Cells[3, 4].HorizontalAlignment := xlRight;

// Обьединяем ячейки ‘A1:A8’
excel.WorkBooks[1].WorkSheets[1].Range[‘A1:A8’].Merge;

// Поворачиваем слова под углом 90 градусов для второго ряда
excel.WorkBooks[1].WorkSheets[1].Rows[2].Orientation := 90;

// Поворачиваем слова под углом 45 градусов для диапазона ячеек ‘B3:D3’
excel.WorkBooks[1].WorkSheets[1].Range[‘B3:D3’].Orientation := 45;

//рисуем границы выделенного диапазона левая
excel.Selection.Borders[xlEdgeLeft].LineStyle := xlContinuous; // стиль линии сплошная
excel.Selection.Borders[xlEdgeLeft].Weight := xlMedium;// толщина линии

//рисуем границы выделенного диапазона верхняя
excel.Selection.Borders[xlEdgeTop].LineStyle := xlContinuous;
excel.Selection.Borders[xlEdgeTop].Weight := xlMedium;

//рисуем границы выделенного диапазона нижняя
excel.Selection.Borders[xlEdgeBottom].LineStyle := xlContinuous;
excel.Selection.Borders[xlEdgeBottom].Weight := xlMedium;

//рисуем границы выделенного диапазона правая
excel.Selection.Borders[xlEdgeRight].LineStyle := xlContinuous;
excel.Selection.Borders[xlEdgeRight].Weight := xlMedium;

//рисуем границы выделенного диапазона вертикальные внутрениие
excel.Selection.Borders[xlInsideVertical].LineStyle := xlContinuous;
excel.Selection.Borders[xlInsideVertical].Weight := xlMedium;

//рисуем границы выделенного диапазона горизонтальные внутрениие
excel.Selection.Borders[xlInsideHorizontal].LineStyle := xlContinuous;
excel.Selection.Borders[xlInsideHorizontal].Weight := xlMedium;

//автозаполнение выделенного диапазона
//для примера заполним область ячеек ‘A10:C10’ словом ‘привет’
//и размножим его вниз еще на пять ячеек ‘A10:C15’

excel.WorkBooks[1].WorkSheets[1].Range[‘A10:C10′].Value:=’привет’;

//выделяем диапазон ячеек ‘A10:C10’
excel.WorkBooks[1].WorkSheets[1].Range[‘A10:C10’].Select;

//автозаполняем (копируем) выделенным диапазоном область ячеек ‘A10:C15’
excel.selection.autofill(excel.WorkBooks[1].WorkSheets[1].Range[‘A10:C15’],xlFillDefault);

//отключаем предупреждения, чтобы не задавал вопросов о сохранении и других
excel.DisplayAlerts := False;

//сохраняем документ в формате Excel 97-2003
excel.ActiveWorkBook.Saveas(GetCurrentDir() + ‘отчет.xls’,xlExcel8);

//сохраняем документ в текущем формате Excel 2007
excel.ActiveWorkBook.Saveas(GetCurrentDir() + ‘отчет.xlsx’);

//закроем все книги
excel.Workbooks.Close;

//закрываем Excel
excel.Application.quit;

//освобождаем интерфейсы
excel := Unassigned;

//обрабатываем ошибки
showmessage(‘Внимание! Произошла ошибка при создании MS Excel приложения’);

//закроем все книги
excel.Workbooks.Close;

//закрываем Excel
excel.Application.quit;

//освобождаем интерфейсы
excel := Unassigned;
end;
end;

При работе с листом Excel мы можем использовать следующие варианты:
— работать с областью Range[‘B3:D3’];
— работать с ячейкой Cells[2, 4] где 2 — ряд, 4 — колонка;
— работать с рядами Rows[1] или с диапазоном рядов Rows[‘1:5’];
— работать с колонками Columns[1] или диапазоном колонок Columns[‘A:I’];

Range[‘A1’] и Cells[1, 1] обозначают одно и тоже.

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

Например так:
//закроем все книги
excel.Workbooks.Close;

//закрываем Excel
excel.Application.quit;

//освобождаем интерфейсы
sheet:=Unassigned; //интерфейс листа если он был создан
WorkBook := Unassigned;//интерфейс рабочей книги если он был создан
excel := Unassigned;//интерфейс самого предложения если он был создан

Ниже привожу пример вывода в Excel из Delphi таблицы умножения с подробными комментариями.

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, comobj, StdCtrls, Excel_TLB;

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
< Private declarations >
public
< Public declarations >
end;

var
Form1: TForm1;
excel: variant; // Переменная в которой создаётся объект EXCEL
MyData: variant; // Переменная в которой формируется таблица умножения
i,j:integer;
implementation

procedure TForm1.Button1Click(Sender: TObject);
begin
try
// Обьект EXCEL
excel := CreateOleObject(‘Excel.Application’);
// Чтоб не задавал вопрос о сохранении документа
excel.DisplayAlerts := false;
// новый документ
excel.WorkBooks.Add;

//объявляем вариантный массив
MyData := VarArrayCreate([1,9,1,9],varVariant);
for I := 1 to 9 do
for J := 1 to 9 do
MyData[i,j]:=i*j;

// Обьединяем ячейки ‘A1:I1’
excel.WorkBooks[1].WorkSheets[1].Range[‘A1:I1’].Merge;
//Пишем заголовок
excel.WorkBooks[1].WorkSheets[1].Range[‘A1′].Value:=’Таблица умножения’;
// Выравнивам заголовок по центру
excel.WorkBooks[1].WorkSheets[1].Range[‘A1’].HorizontalAlignment := xlCenter;
// задаем ширину колонок с A по I
excel.WorkBooks[1].WorkSheets[1].Columns[‘A:I’].ColumnWidth := 3;

//выделяем область таблицы умножения [‘A2:I10’] и рисуем границы
excel.WorkBooks[1].WorkSheets[1].Range[‘A2:I10’].select;
//рисуем границы выделенного диапазона левая
excel.Selection.Borders[xlEdgeLeft].LineStyle := xlContinuous; // стиль линии сплошная
excel.Selection.Borders[xlEdgeLeft].Weight := xlThin;// толщина линии
//рисуем границы выделенного диапазона верхняя
excel.Selection.Borders[xlEdgeTop].LineStyle := xlContinuous;
excel.Selection.Borders[xlEdgeTop].Weight := xlThin;
//рисуем границы выделенного диапазона нижняя
excel.Selection.Borders[xlEdgeBottom].LineStyle := xlContinuous;
excel.Selection.Borders[xlEdgeBottom].Weight := xlThin;
//рисуем границы выделенного диапазона правая
excel.Selection.Borders[xlEdgeRight].LineStyle := xlContinuous;
excel.Selection.Borders[xlEdgeRight].Weight := xlThin;
//рисуем границы выделенного диапазона вертикальные внутрениие
excel.Selection.Borders[xlInsideVertical].LineStyle := xlContinuous;
excel.Selection.Borders[xlInsideVertical].Weight := xlThin;
//рисуем границы выделенного диапазона горизонтальные внутрениие
excel.Selection.Borders[xlInsideHorizontal].LineStyle := xlContinuous;
excel.Selection.Borders[xlInsideHorizontal].Weight := xlThin;

//присваиваем диапазону [‘A2:I10’] значения вариантного массива MyData это значительно ускоряет работу, нежели вывод по //ячеечно

Источник

Z-7000

0 / 0 / 0

Регистрация: 07.02.2012

Сообщений: 40

1

03.07.2014, 08:20. Показов 8751. Ответов 6

Метки нет (Все метки)


Студворк — интернет-сервис помощи студентам

Добрый день!
Нужна ваша помощь знатоки! )
Есть шаблон документа, я его заполняю и делаю копию. В этом документе есть несколько листов.
И нужно что одни ячейки листа А были ровны ячейкам листа В. все вроде бы просто!!!!)
Для этого использовал формулы типа:
1) =ЕСЛИ(B!AD9<>»»;B!AD9;»»)
и
2) =СЦЕПИТЬ(B!AD9)
Пришлось их, т.к. если писать просто (=B!AD9), получаю ноль, заполняемая ячейка будет пуста.
Но пошли проблемы!!! Когда копирую из шаблона листы

Delphi
1
WorkSheet1.WorkSheets[1].Copy(After:=WorkSheet2.WorkSheets[1]);



формулы теряются (((
Если пытаюсь cоpдать формулу из Delphi в Excel, используя первую формулу:

Delphi
1
WorkSheet2.WorkSheets[2].Cells[13,10].Formula:= '=ЕСЛИ(Z!AD9<>"";Z!AD9;"")';

грязно ругается!!!
Если пытаюсь cоpдать формулу из Delphi в Excel, используя вторую формулу:

Delphi
1
WorkSheet2.WorkSheets[2].Cells[13,10].Formula:= '=СЦЕПИТЬ(Z!AD9)';

не ругается. Но в ячейке стоит #ИМЯ?, нужно зайти в ячейку и нажать Enter что отработала формула.
Как победить это дело нужно чтобы при заполнении B, А становилось равно B и всего!!!



0



Mawrat

13094 / 5875 / 1706

Регистрация: 19.09.2009

Сообщений: 8,808

03.07.2014, 09:37

2

Лучший ответ Сообщение было отмечено Z-7000 как решение

Решение

Цитата
Сообщение от Z-7000
Посмотреть сообщение

Для этого использовал формулы типа:
1) =ЕСЛИ(B!AD9<>»»;B!AD9;»»)
и
2) =СЦЕПИТЬ(B!AD9)

Достаточно формулы №1.

Цитата
Сообщение от Z-7000
Посмотреть сообщение

Когда копирую из шаблона листы
WorkSheet1.WorkSheets[1].Copy(After:=WorkSheet2.WorkSheets[1]);


формулы теряются (((

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

Цитата
Сообщение от Z-7000
Посмотреть сообщение

Если пытаюсь cоpдать формулу из Delphi в Excel, используя первую формулу:
WorkSheet2.WorkSheets[2].Cells[13,10].Formula:= ‘=ЕСЛИ(Z!AD9<>»»;Z!AD9;»»)’;
грязно ругается!!!

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

Код

=IF(B!AD9<>"";B!AD9;"")

Цитата
Сообщение от Z-7000
Посмотреть сообщение

WorkSheet2.WorkSheets[2].Cells[13,10].Formula:= ‘=СЦЕПИТЬ(Z!AD9)’;
не ругается. Но в ячейке стоит #ИМЯ?, нужно зайти в ячейку и нажать Enter что отработала формула.

Как выше уже упоминалось — в случае программной записи формулы надо задавать в варианте для английского языка. После записи формул надо или выполнить перерасчёт отдельного листа:

Delphi
1
WorkSheetNew.Calculate;

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

Delphi
1
exApplication.Calculate;


В общем, надо разобраться с кодом, который идёт после строки:

Delphi
1
WorkSheet1.WorkSheets[1].Copy(After:=WorkSheet2.WorkSheets[1]);

Потому, что выполнение самой этой строки не приводит к потере формул.

Добавлено через 19 минут

Цитата
Сообщение от Mawrat
Посмотреть сообщение

После записи формул надо или выполнить перерасчёт отдельного листа:

Вернее, лучше так — если формул много, то перед их записью надо отключить режим автоматического пересчёта. А после записи всех формул, вновь включить автоматический пересчёт:

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
const
  xlManual = -4135;
  xlAutomatic = -4105;
var
  exApp : OleVariant;
...
begin
...
  exApp.Calculation := xlManual; //Переключение на режим ручного пересчёта.
  //Запись формул в ячейки.
  ...
  exApp.Calculation := xlAutomatic; //Вновь включаем автоматический пересчёт.



2



Z-7000

0 / 0 / 0

Регистрация: 07.02.2012

Сообщений: 40

04.07.2014, 03:41

 [ТС]

3

Большое спасибо за такой прекрасный ответ.
Совершенно верно, что нужно писать все функции на английском языке ) я не обратил внимания.
Тут еще я допустил ошибку:

Delphi
1
=IF(B!AD9<>"";B!AD9;"")

Excel использует в формуле «;» — точку с запятой, но для Delphi это ошибка, нужна просто запятая:

Delphi
1
=IF(B!AD9<>"",B!AD9,"")

В Excel уже будет все как нужно!
И точно, копирование не удаляет формулы, это я затирал формулы в процессе заполнения листов.!!!
И получается что цифры:

Delphi
1
2
  xlManual = -4135;
  xlAutomatic = -4105;

это диапазон строк в котором происходит перерасчет?



0



Mawrat

13094 / 5875 / 1706

Регистрация: 19.09.2009

Сообщений: 8,808

04.07.2014, 08:45

4

Цитата
Сообщение от Z-7000
Посмотреть сообщение

Excel использует в формуле «;» — точку с запятой, но для Delphi это ошибка, нужна просто запятая:

Правильно. Только это не в Delphi дело. Это в Excel такая особенность записи формул через программу — что аргументы надо разделять запятой, а не точкой с запятой.

Цитата
Сообщение от Z-7000
Посмотреть сообщение

И получается что цифры:

Delphi
1
2
  xlManual = -4135;
  xlAutomatic = -4105;

это диапазон строк в котором происходит перерасчет?

Это константы, с помощью которых задаётся режим перерасчёта формул. Если мы пишем так:

Delphi
1
2
//Здесь exApp ссылается на интерфейс корневого объекта Excel - Excel.Application.
exApp.Calculation := xlAutomatic;

то включается автоматический режим перерасчёта. В этом случае каждый раз, когда мы записываем формулу в ячейку, Excel выполняет перерасчёт. Этот режим чаще всего задействован по начальным установкам.
А если мы пишем так:

Delphi
1
2
//Здесь exApp ссылается на интерфейс корневого объекта Excel - Excel.Application.
exApp.Calculation := xlManual;

то Excel не будет автоматически выполнять расчёты по формулам. Расчёт будет выполнен, только, если вызвать метод exApp.Calculate (если exWorkSheet.Calculate для пересчёта отдельного листа). Это бывает полезно, когда на листы надо записать большое количество формул — чтобы Excel во время этого процесса не выполнял перерасчёты.



0



0 / 0 / 0

Регистрация: 07.02.2012

Сообщений: 40

04.07.2014, 09:38

 [ТС]

5

Все предельно ясно )
И еще один маленький вопрос, больше относящийся к Excel.
Есть ячейка с текстом и если текст в ней подчеркнут, то другая ячейка становилась ей ровна.
что-то типа

Код

=IF(лист!N83Font.Underline=true,лист!N83,"")

а найти пример не могу (



0



13094 / 5875 / 1706

Регистрация: 19.09.2009

Сообщений: 8,808

04.07.2014, 10:38

6

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



0



0 / 0 / 0

Регистрация: 07.02.2012

Сообщений: 40

04.07.2014, 11:04

 [ТС]

7

) Да через программу это легко согласен.!
Но просто программа отработала, а есть необходимость редактировать данные в Excel и только в одном листе,
а в остальных автоматом изменяются значения.
Ладно, буду думать) если у вас есть идеи пишите, буду рад.!

Еще маленький вопрос уже программный, Excel открывается нормально, но почему-то за формой программы, такое заметил с в десятом Excel. Как заставить его открываться поверх, всех окон и в развернутом виде, а не маленьким прямоугольником, что тоже бывает.!.?



0



IT_Exp

Эксперт

87844 / 49110 / 22898

Регистрация: 17.06.2006

Сообщений: 92,604

04.07.2014, 11:04

7

 
EgorT
 
(2004-01-08 12:24)
[0]

Добрцый день! Есть такая проблема: хочется из Delphi 5 записывать в MS Excel всякие разные формулы, отличные от SUM. Помогите кто знает как это делать!


 
Романов Р.В.
 
(2004-01-08 12:25)
[1]

cells.Formula := «=МИН(A1:A10)»;


 
REP
 
(2004-01-08 12:31)
[2]

cells.Formula := «=MIN(A1:A10)»; Вроде как русские формулы он не понимает. Хотя может и от версии зависит.


 
EgorT
 
(2004-01-08 12:34)
[3]

Не помогает пишет «#ИМЯ?» в той ячейке, то есть результат считать не могу, или если записть формулу «=ЕСЛИ(A1=10;A2+A3;0)» тоже ничего хорошего не получилось


 
EgorT
 
(2004-01-08 12:35)
[4]

например Сумм понимает замечательно а все остальное нет


 
Романов Р.В.
 
(2004-01-08 13:00)
[5]

A1 пиши на английской раскладке


 
REP
 
(2004-01-08 13:06)
[6]

Вместо точки с запятой используй ЗАПЯТУЮ

А в сумм ты не используешь точку с запятой

Типа:

«=ЕСЛИ(A1=10
, A2+A3,0)»


 
EgorT
 
(2004-01-08 13:10)
[7]

А1 пишу по английски, а на счет запятой попробую


 
Карелин Артем
 
(2004-01-08 13:26)
[8]

Делай макрос и формулу бери из макроса. К примеру
=ЕСЛИ(H8=12;G3;12) на самом деле будет
"=IF(R[7]C[7]=12,R[2]C[6],12)"


 
EgorT
 
(2004-01-08 13:39)
[9]

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


 
REP
 
(2004-01-08 13:45)
[10]

Карелин Артем © (08.01.04 13:26) [8]

Ну не обязательно уж прямо R[7]C[7] Можно и обычно использовать H8, однако с синтаксисом нужно быть поосторожнее. Можно в Екселе находить нужную формулу по русски, а затем в «смотри также»(See also) находить ее англоязычный синтаксис


 
Карелин Артем
 
(2004-01-08 13:52)
[11]

REP © (08.01.04 13:45) [10]

Не обязательно. Это я через запись макроса получил.

EgorT (08.01.04 13:39) [9]

Именно не понял идею. Через макрос Названия формул надо получать. Хранить из не надо.


 
REP
 
(2004-01-08 14:03)
[12]

Карелин Артем © (08.01.04 13:52) [11]

Сидим и говорим друг другу «не обязательно, не обязательно»

Все таки нагляднее H8 (роднее для тех кто ексель знает немного)

А так пиши как угодно, не спорю.

:))

EgorT (08.01.04 13:39) [9]

А идея рассмотрена в соседней ветке:

http://delphimaster.net/view/1-1073549258/

По сути однотипные вопросы-то. И решение проблемы одно…


Поиск данных на листе.

Предлагаю поискать все ячейки, содержащие строку (или
подстроку) «Text», и изменить цвет фона этих ячеек. Для этого я использовал
методы Find и FindNext. На форму была добавлена кнопка, в обработчике которой
появился следующий код:

procedure TForm1.btnFindClick(Sender: TObject);
var ISheet: Excel8TLB._Worksheet;
IFirst, IRange: Excel8TLB.Range;
FirstAddress, CurrentAddress: string;
UsedRange: OLEVariant;
begin
if Assigned(IWorkbook) then
try
ISheet := IWorkbook.Worksheets.Item['Лист1'] as Excel8TLB._Worksheet;
try
UsedRange := ISheet.UsedRange[0];
IDispatch(IFirst) := UsedRange.Find(What:='Text', LookIn := xlValues, 
SearchDirection := xlNext);
if Assigned(IFirst) then begin
IRange := IFirst;
FirstAddress := IFirst.Address[EmptyParam, EmptyParam, xlA1, EmptyParam, EmptyParam];
repeat
IRange.Interior.ColorIndex := 37;
IDispatch(IRange) := UsedRange.FindNext(After := IRange);
CurrentAddress := IRange.Address[EmptyParam, EmptyParam, xlA1,
EmptyParam, EmptyParam];
until FirstAddress = CurrentAddress;
end;
finally
IRange := nil;
IFirst := nil;
ShowExcel;
end;
except
raise Exception.Create('Не могу чего-то сделать!');
end;
end;

Думаю, у каждого увидевшего этот код возникнет ощущение
неудовлетворенности. Да, в выделенной красным строке никаким ранним связыванием
и не пахнет. Более того, если вы попробуете вызвать метод Find с указанными
параметрами, заменив остальные на EmptyParam, вы получите исключение. Есть места
в Excel Type Library, работающие с ошибками. Я знаю достаточно этих мест. В
таких случаях я использую приведенный здесь прием. Я проверяю работоспособность
кода в редакторе VBA, а затем перехожу на позднее связывание. Так мне удалось
обойти несколько серьезных, по моему мнению, ошибок в Excel TLB. Раннее
связывание не должно быть догмой хотя бы из-за этого. Более того, перейдя
полностью на ранее связывание, мы получим более компактный, а следовательно и
читаемый код:

procedure TForm1.btnFindClick(Sender: TObject);
var ISheet: Excel8TLB._Worksheet;
UsedRange, Range: OLEVariant;
FirstAddress: string;
begin
if Assigned(IWorkbook) then
try
ISheet := IWorkbook.Worksheets.Item['Лист1'] as Excel8TLB._Worksheet;
UsedRange := ISheet.UsedRange[0];
Range := UsedRange.Find(What:='Text', LookIn := xlValues, SearchDirection := xlNext);
if not VarIsEmpty(Range) then begin
FirstAddress := Range.Address;
repeat
Range.Interior.ColorIndex := 37;
Range := UsedRange.FindNext(After := Range);
until FirstAddress = Range.Address;
ShowExcel;
end;
except
raise Exception.Create('Не могу чего-то сделать!');
end;
end;

Перемещение данных между листами.

Несколько раз меня спросили о том, как перемещать данные между
листами. Я бы сделал это вот так:

procedure TForm1.btnMoveDataClick(Sender: TObject);
var ISheetSrc, ISheetDst: Excel8TLB._Worksheet;
IRangeSrc, IRangeDst: Excel8TLB.Range;
begin
if Assigned(IWorkbook) then
try
ISheetSrc := IWorkbook.Worksheets.Item['Лист1'] as Excel8TLB._Worksheet;
ISheetDst := 
IWorkbook.Worksheets.Add(EmptyParam, ISheetSrc, 1, EmptyParam, 0) as _Worksheet;
IRangeSrc := ISheetSrc.Range['TestRange2', EmptyParam];
IRangeDst := ISheetDst.Range['D4', EmptyParam];
IRangeSrc.Copy(IRangeDst);
finally
IRangeDst := nil;
IRangeSrc := nil;
ISheetDst := nil;
ISheetSrc := nil;
end;
end;

Метод Copy интерфейса Range принимает в качестве параметра
любой другой Range. Причем, совсем не важно, совпадают ли размеры источника и
получателя, так как данные копируются начиная с левой верхней ячейки получателя
в количестве, определенном размером источника. (О, завернул!) Для затравки
хотелось бы показать код, который выполняет ту же задачу, но через буфер обмена
(а вдруг в Word вставлять будем):

procedure TForm1.btnMoveDataClick(Sender: TObject);
var ISheetSrc, ISheetDst: Excel8TLB._Worksheet;
IRangeSrc, IRangeDst: Excel8TLB.Range;
begin
if Assigned(IWorkbook) then
try
ISheetSrc := IWorkbook.Worksheets.Item['Лист1'] as Excel8TLB._Worksheet;
ISheetDst := 
IWorkbook.Worksheets.Add(EmptyParam, ISheetSrc, 1, EmptyParam, 0) as _Worksheet;
IRangeSrc := ISheetSrc.Range['TestRange2', EmptyParam];
IRangeDst := ISheetDst.Range[ 'D4', EmptyParam];
IRangeSrc.Copy(EmptyParam); // так кладем в Clipboard
ISheetDst.Paste(IRangeDst, EmptyParam, 0); // а вот так достаем оттуда
finally
IRangeDst := nil;
IRangeSrc := nil;
ISheetDst := nil;
ISheetSrc := nil;
end;
end;

Проект — SampleExcel (в архиве с данной
статьёй).

Часть 5. Передача данных разного типа.

Как и прежде, я беру проект-пример из предыдущей своей статьи
и переделываю его. Напомню, что в нем используется импортированная в Delphi 4
библиотека типов Excel (правда, исходный код я пишу уже в Delphi 5). Свои
примеры я тестирую с помощью Excel 2000 с установленным пакетом обновлений
Service Release 1. Впрочем, я уверен, что все примеры вы сможете откомпилировать
в Delphi 4 и использовать с Excel 97 SR2 и Excel 2000 без SR1. Обращаю внимание
на установку SR2 для Excel 97. Это обязательное условие, так как без этого
обновления Excel содержит очень неприятную ошибку, периодически возникающую при
закрытии книг. Поэтому, пожалуйста, будьте внимательны, господа!


Какие данные мы используем?..

«Всяческие»! Да, каждый из нас использует в своих приложениях
все многообразие типов данных, с которыми способен справиться компилятор и
операционная система. В принципе, можно было бы описать решение проблемы для
всего этого «многообразия». Но! Я всегда утверждал и буду утверждать, что типы
данных, для которых нельзя написать Cell.Value = NewValue, бесполезно
использовать в Excel. Я не «влюблен» в Excel. Но я твердо уверен в том, что
Excel в сегодняшнем его состоянии — одно из мощнейших средств анализа
корпоративных данных. И я до сих пор не могу найти другого применения картинкам
в книгах Excel, кроме как наведение красоты. Поэтому я остановлюсь только на
способах передачи целых и вещественных чисел, строк, дат и логических значений.
В общем, всего того, что так надоело нам в наш быстротекущий media-век.

Важно! Проект-пример содержит одну форму, в
обработчиках OnCreate и OnDestroy которой автоматически создается и
освобождается Excel.Application. Причем, для этого я использовал методы из
предыдущих примеров — CreateExcel, ShowExcel и ReleaseExcel. Особое внимание
хочу обратить на ReleaseExcel, с помощью которого освобождается интерфейс
Excel.Application. Если же необходимо закрыть Excel, вызывайте перед
освобождением интерфейса метод Quit этого интерфейса (у себя я закомментировал
эту строку). На форму я поместил таблицу (TTable) из DBDEMOS — CUSTOMER.DB.
Чтобы видеть хоть что-то, я использовал для этой таблицы DBGrid и навигатор. В
правой части формы вы увидите кнопку со странным названием «Send data» и группу
переключателей под ней. С помощью этой группы вы сможете выбрать один из
рассмотренных в этой статье вариантов передачи данных в Excel (данные я беру из
вышеназванной таблицы). После выбора варианта передачи и нажатия кнопки в Excel
создается новая книга на основе шаблона Test.xls — книги, которую я прилагаю
вместе с проектом. В эту книгу из таблицы переносятся значения полей из всех
записей. При переносе я измеряю количество миллисекунд, затраченных на этот
перенос, и помещаю это количество в ячейку A1 созданной книги.

И еще. При создании примера я старался избегать лишнего кода,
который в любом другом случае добавил бы законченность алгоритмам. Меня стоило
бы основательно поругать за то, что я не запоминаю закладок при проходе по
таблице, использую значения полей, забывая о DisplayText, и просто переношу
значения в книгу без какого-либо форматирования ячеек. Наверняка, вы найдете еще
несколько моментов, которые я совсем упустил из вида. Попросту, красота кода
уступила свое место желанию сосредоточиться на единственной цели — эффективной
передаче данных. Единственное, что я сделал, так это избавился от возможности
вмешательства пользователя в процесс переноса данных, отключив (и включив затем)
у Excel свойства Interactive и ScreenUpdating, а также вызвав DisableControls
для набора данных.

Какие же варианты я предложу на суд читателя? Вариантов и
возможностей передачи данных в Excel существует достаточно много — от очень
«заумных» (BIFF) до экзотических (сохраним в текстовый файл и затем его
откроем). Все они имеют какие-то свои достоинства и недостатки. В этой статье я
расскажу об одних из самых простых и эффективных решениях этой проблемы
(название раздела все-таки обязывает — HelloWorld!). Правда, первый описанный
здесь способ, у меня ничего кроме зубной боли не вызывает. Итак…


Не делайте так — клиническая смерть!

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

Первый переключатель на форме (с заголовком «Value :=»)
скрывает за собой вызов процедуры ToNewValue. Вот ее исходный код:

procedure TForm1.ToNewValue(ISheet: IxlWorksheet);
var Row, Column, i: integer;
begin
tblCust.First;
Row := StartRow;
tblCust.First;
while not tblCust.EOF do begin
Column := StartColumn;
for i := 0 to tblCust.Fields.Count - 1 do begin
ISheet.Cells.Item[Row, Column].Value := FieldToVariant(tblCust.Fields[i]);
Inc(Column);
end;
Inc(Row);
tblCust.Next;
end;
end;

Что в ней особенного? Да, это обычный проход по всей таблице
(First; while not EOF do Next;) и по всем ее полям (вложенный for). Но!
Во-первых, в этом примере я всегда начинаю переносить данные с ячейки,
определенной константами StartRow и StartColumn. Во-вторых, ожидаемый вами
оператор присваивания «Cell.Value := Field.Value» я заменил на «Cell.Value :=
FieldToVariant(Field)». То есть, в отличие от классического, «из учебников»,
примера я использую свою функцию получения вариантного значения поля.

Если присмотреться к исходному тексту функции FieldToVariant,

function FieldToVariant(Field: TField): OLEVariant;
begin
Result := '';
case Field.DataType of
ftString, ftFixedChar, ftWideString, ftMemo, ftFmtMemo: Result := '''' + Field.AsString;
ftSmallint, ftInteger, ftWord, ftLargeint, ftAutoInc: Result := Field.AsInteger;
ftFloat, ftCurrency, ftBCD: Result := Field.AsFloat;
ftBoolean: Result := Field.AsBoolean;
ftDate, ftTime, ftDateTime: Result := Field.AsDateTime;
end;
end;

то можно разглядеть причину. Кроме достаточно глупых
«AsInteger», «AsFloat» и пр. я добавляю в начало значений строковых полей
одиночную кавычку. Вы, наверняка, помните, что ввод в формулу ячейки первым
символом одиночной кавычки заставляет Excel принимать остальные символы как
текст. Но, это касается формул ячеек, а не их значений!? Попробуйте убрать
добавление этой кавычки и перекомпилировать проект. Конечно, и в этом варианте
все будет работать. Но (предлагаю кощунственный метод) отредактируйте поле
«Company» в первой записи таблицы, введя туда строку «3/7». Не увидите ли вы в
полученной книге вместо этой строки дату или результат деления (зависит от
языковых настроек ОС)? Столь же некорректный результат будет получен и при
попытке передачи строки «0001», которая будет воспринята как число 1. Благо,
одиночная кавычка в начале строки решает эту проблему даже при присваивании в
Value (а не в Formula).

Впрочем, я не намерен долго останавливаться на этом варианте.
Все дело в значении ячейки A1 в полученной книге. На моем компьютере перенос
всей таблицы занял более 4 секунд. И это на не более полусотне записей. А что
было бы, если бы количество записей перевалило за пару десятков тысяч? Кстати,
повторные запуски показали колебание этого времени в пределах от трех до пяти
секунд. Думаю, что такие колебания были связаны только с файловым кэшем ОС. Так
что, «Не делайте так!»


Больному уже лучше. Правда, он все еще в реанимации.

На что же уходит время в предыдущем варианте? Все просто!
Львиная доля времени уходит на вызовы интерфейсов внешнего COM-сервера. И, не
смотря на то, что мы используем ранее связывание с библиотекой типов, это так.
Еще мой любимый классик (Калверт, знаете ли) писал о нетерпимости к вызовам
интерфейсов внешних OLE-серверов в больших циклах. Как видите, классик прав.

Наша задача — избавиться от вызова Cell.Value в цикле. И это
решаемо с помощью вариантных массивов. Вот так:

procedure TForm1.ToVarArray(ISheet: IxlWorksheet);
var Row, Column, i: integer;
IR1, IR2: IxlRange;
Arr: OLEVariant;
begin
Arr := VarArrayCreate([1, tblCust.RecordCount, 1, tblCust.Fields.Count], varVariant);
Row := 1;
tblCust.First;
while not tblCust.EOF do begin
Column := 1;
for i := 0 to tblCust.Fields.Count - 1 do begin
Arr[Row, Column] := FieldToVariant(tblCust.Fields[i]);
Inc(Column);
end;
Inc(Row);
tblCust.Next;
end;
IDispatch(IR1) := ISheet.Cells.Item[StartRow, StartColumn];
IDispatch(IR2) := ISheet.Cells.Item[StartRow + tblCust.RecordCount - 1, StartColumn + tblCust.Fields.Count - 1];
ISheet.Range[IR1, IR2].Value := Arr;
end;

Здесь я использую вариантный массив Arr, который
предварительно создается с размерами таблицы (количество записей на количество
полей). Благо Microsoft построила очень четкую схему работы с вариантными
массивами и интерфейсами, их «понимающими» (этим и пользуюсь). Из кода видно,
что я по-прежнему прохожу всю таблицу, запоминая в элементах массива значения
полей, полученных из вышеописанной функции FieldToVariant. Мы, ведь, снова
используем варианты, и проблема строки «3/7» остается. Последние три строки
процедуры позволяют получить верхнюю левую и нижнюю правую ячейки области, в
которую будут перенесены данные. А, затем, одним присваиванием в «Область.Value»
я переношу данные из массива в ячейки этой области. Хорош способ, не правда ли?
Код максимально прост. Время, полученное в ячейке A1 на порядок меньше. Правда,
есть несколько проблем.

Главное, что бросилось бы в глаза опытного
Delphi-разработчика, это создание массива в начале процедуры. Известно ли
количество записей SQL-запроса после его открытия? Не всегда (FechAll). Хорошо,
можно создать пустой массив и делать ему VarArrayRedim. Вряд ли! Так как
количество записей — есть первое измерение вариантного массива (необходимо здесь
тире или нет???). А я не нашел до сих пор способа изменить первую размерность
вариантного массива при наличии второй. Может, кто подскажет начинающему (про
начинающего — правда)!!! Возможно, было бы правильно создать массив массивов
(понимаете о чем я?). Но, что-то не заладилось там, Наверху. Поэтому такое
решение не проходит. Точнее проходит, но как-то не очень хорошо — попробуйте!

Тем не менее, этот вариант вполне «живуч» при осторожном его
использовании и на небольших объемах данных. Скорость нормальная, проблем с
«3/7» нет. В общем, больной будет жить!

Часть 6. Передача данных используя буфер обмена и DDE.
Clipboard.

Совсем недавно мне пришло очередное гневное послание на тему
буфера обмена — Clipboard. Объясню. XL Report очень долго использовал только
буфер обмена для передачи данных из приложения в Excel. Дело в том, что при
таком варианте (а я его здесь опишу) достигается практически максимальная
скорость переноса данных. Дело в том, что в буфер обмена «кладется» длинная
строка, содержащая строковые значения полей набора данных (AsString),
разделенные символом табуляции. Записи отделяются друг от друга переводом строки
(#10). Собственно, этот формат известен в научных кругах как CSV (разделитель
между значениями). Долгое время это меня устраивало, пока XL Report
использовался только нашими разработчиками и ограниченным кругом клиентов фирмы.
Но тут мы решили выложить это решение в Сеть. И…

Каюсь. Я никак не беспокоился за сохранность содержимого
буфера обмена. Понятное дело, это не очень правильно. Но, так было. Так есть и
сейчас. Правда, по другим причинам. Для того, чтобы «выжать» из Excel
максимальное быстродействие, приходится использовать определенные методы и
свойства его интерфейсов. А их использование не оставляет ничего, кроме как
уничтожение содержимого буфера обмена. В общем, сейчас я покажу максимально
возможное (в этой статье!!!) решение по переносу данных — CSV. Итак:

procedure TForm1.ToCSV(ISheet: IxlWorksheet);
var i: integer;
IR1, IR2: IxlRange;
Buff: String;
begin
Buff := '';
tblCust.First;
while not tblCust.EOF do begin
for i := 0 to tblCust.Fields.Count - 1 do begin
Buff := Buff + FieldToStr(tblCust.Fields[i]);
if i < (tblCust.Fields.Count - 1) then
Buff := Buff + #9;
end;
tblCust.Next;
if not tblCust.EOF then
Buff := Buff + #10;
end;
BufferToClipboard(Buff);
try
IDispatch(IR1) := ISheet.Cells.Item[StartRow, StartColumn];
IDispatch(IR2) := ISheet.Cells.Item[StartRow + tblCust.RecordCount - 1, 
StartColumn + tblCust.Fields.Count - 1];
OLEVariant(ISheet.Range[IR1, IR2]).PasteSpecial;
finally
Clipboard.Clear;
end; 
end;

Как я и писал выше, в строковый буфер Buff собирается вся
таблица. Строковые значения полей я разделяю символом табуляции, а в «конце»
записи добавляю перевод строки. Все значения я заключаю дополнительно в двойные
кавычки. Затем вызовом процедуры BufferToClipboard я помещаю содержимое этой
переменной в буфер обмена и делаю «хитрый» вызов PasteSpecial для области, в
которую будут помещены данные. Вот и все?! Нет, есть еще проблемы.

Во-первых, процедура BufferToClipboard — вещь не стандартная.
Она создана как альтернатива методу SetTextBuf класса TClipboard. Наверняка, все
знают что в VCL доступна глобальная переменная Clipboard, экземпляр класса
TClipboard, инкапсулирующего свойства и методы доступа к этому самому буферу
обмена. И, собственно, вызов SetTextBuf позволяет поместить строку в буфер. Но!

SetTextBuf помещает в буфер обмена текст в формате CF_TEXT —
обычный текст с однобайтовым представлением символов, что не есть хорошо.
Точнее, это совсем не хорошо, если вы работаете с «русскими буквами» на разных
операционных системах от MS, причем, разных с точки зрения локализации. Именно
тогда и возникают у пользователей вопросы при попытке прочитать некий набор
«закорючек», отдаленно напоминающих письмена племени зибару. Поэтому я
предпочитаю UNICODE, вставка которого в буфер обмена и реализована в этой
процедуре. Ее текст я не буду приводить в этой статье, так как это потребует
лишних для этого объяснений. Сама процедура присутствует в исходных текстах
проекта-примера. Поэтому знатоков этого дела отсылаю к ним, а таким начинающим,
как и я, просто рекомендую ее использовать в последующих своих разработках (при
необходимости).

UNICODE — это первая проблема, которая была решена. Но при
использовании CSV есть и другие. И, главная, из них — «3/7». Без вмешательства в
содержимое поля (аналогично добавлению одиночной кавычки при вариантах) ее
нельзя обойти никак. Я добавляю пробел. Да, тривиального пробела вполне хватает
для решения этой проблемы. И замеченная вами функция FieldToStr как раз это и
делает.

По поводу «хитрого» PasteSpecial. При «правильном» вызове
метода PasteSpecial интерфейса Range я столкнулся с неразрешимыми проблемами.
Поэтому я привел к варианту область и заставил ОС и сам Excel самостоятельно
разбираться с тем, что и с какими параметрами я вызываю. Часто, при разработке с
библиотеками типов от MS такой ход экономит время и, главное, сохраняет здоровье
и нормальное состояние нервной системы. Не используйте его все время, но и не
пренебрегайте им. Итак, при использовании CSV и буфера обмена мы достигли
«громаднейшей» скорости передачи данных, обойдя при этом несколько проблем.

Недостатки, которые заметят критики и просто опытные
разработчики. Переданное строковое значение «0001» предстает перед изумленным
пользователем числом 1. Это можно обойти только через предварительное
форматирование конкретной ячейки в текстовый формат. Подчеркиваю,
предварительно, то есть перед переносом данных. И, по-прежнему, содержимое
буфера обмена не сохраняется. Более того, оно затем нагло очищается вызовом
Clipboard.Clear. «Мы его теряем!»


DDE.

Думаю, вы уже заметили, что один из переключателей вариантов
имеет название, состоящее из зловещего сочетания букв — DDE. Первое, что вы
можете почувствовать при виде этих букв, — это застоялый запах плесени и
старения. Да, DDE — пережиток старого доброго времени (а, кажется, это было
совсем недавно — «как молоды мы были»), времени DOS-резидентов, командной
строки, капитана Нортона и первых (не смотря на их номер — 3.0) «форточек».
Черт, тут жизнь уже проходит, а DDE все еще жив. И слава Богу! Ведь, мы решим
«главную» проблему — сохранение содержимого буфера обмена. Вот так:

procedure TForm1.ToDDE(ISheet: IxlWorksheet);
var xlDDE: TDDEClientConv;
i: integer;
IR1, IR2, IRange: IxlRange;
Buff: string;
begin
Buff := '';
tblCust.First;
while not tblCust.EOF do begin
for i := 0 to tblCust.Fields.Count - 1 do begin
Buff := Buff + FieldToStr(tblCust.Fields[i]);
if i < (tblCust.Fields.Count - 1) then
Buff := Buff + #9;
end;
tblCust.Next;
if not tblCust.EOF then
Buff := Buff + #10;
end;
IDispatch(IR1) := ISheet.Cells.Item[StartRow, StartColumn];
IDispatch(IR2) := ISheet.Cells.Item[StartRow + tblCust.RecordCount - 1,
StartColumn + tblCust.Fields.Count - 1];
IRange := ISheet.Range[IR1, IR2];
xlDDE := TDDEClientConv.Create(Self);
try
if xlDDE.SetLink('EXCEL', ISheet.Name) then
xlDDE.PokeData(OLEVariant(IRange).Address[ReferenceStyle:=xlR1C1], PChar(Buff));
finally
xlDDE.Free;
end;
end;

Все реже я встречаю книги, где было бы описано взаимодействие
приложений посредством DDE. Многие и вовсе думают, что DDE уже давно умер. Но,
нет, «жив курилка». И, более того, это одно из самых быстрых решений по передаче
данных в Excel. И, что самое интересное, Excel по-прежнему поддерживает DDE и
все DDE-команды, которые стали доступны со времен версии 4.0. И по-прежнему
будет несказанно рад тот счастливчик, который обнаружит в непроходимых джунглях
Сети файл под названием «excel40macro.hlp», ибо там он найдет все, что нужно для
быстрой и качественной работы с Excel. Это вам не интерфейсы «пользовать». Но,
вернемся к исходному тексту.

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

Переменная xlDDE используется для доступа к Excel посредством
DDE. Если опустить теорию, напрямую обратившись к практике, то можно увидеть
следующий алгоритм ее использования. Во-первых, создается экземпляр класса
TDDEClientConv. Во-вторых, вызовом SetLink происходит соединение через DDE с
запущенным Excel. SetLink возвращает true, если это соединение успешно. А далее
происходит вызов метода PokeData, одним из параметров которого является
строковый буфер Buff. Второй параметр — это адрес области в формате R1C1. Вот и
все. Думаю, это работает и у вас. Скорость сравнима с CSV через буфер обмена.
Плюс, здесь буфер обмена мы совсем не используем. Но!

Попробуйте несколько раз подряд быстро нажать кнопку «Send
data» с этим вариантом передачи данных. У меня Excel просто виснет. Точнее, он
что-то делает, загружая на все сто процессор. Благо, Windows NT безболезненно
позволяет снять задачу. Тем, у кого Win9x, повезло меньше и, видимо, им придется
перезагрузиться. Почему это происходит? Меня смутила вот эта строка в реализации
TDDEClientConv:

hdata := DdeClientTransaction(Pointer(hszDat), DWORD(-1), FConv, hszItem,
FDdeFmt, XTYP_POKE, TIMEOUT_ASYNC, nil);

Точнее параметр TIMEOUT_ASYNC, позволяющий передавать данные
асинхронно. Вот и сыплется Excel, не выдерживая реализации DDE-клиента от
Borland/Inprise. Впрочем, Borland тоже не причем. Для себя я создал потомка
класса TDDEClientConv, добавив ему новый метод xlPokeData, в котором просто
заменил эту строку на:

Const xddeTransactionTimeOut = 100000;
...
hdata := DdeClientTransaction(Pointer(hszDat), DWORD(-1), Conv, hszItem,
CF_XLTABLE, XTYP_POKE, xddeTransactionTimeOut, nil);
...

И все в порядке — работает.

Я не стану описывать подробности взаимодействия процессов
через DDE по, думаю, понятным вам причинам. Все это давно описано в классике
жанра — документации по Delphi. Тем не менее, по-прежнему остается проблема со
строкой «0001». И останется она при этом варианте нерешенной, так как здесь
используются строковые представления всех значений полей. И где же выход,
спросите вы? Выход прост.

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

Чтобы в нем использовались native представления данных, где
число было бы не строкой, а привычным набором из четырех (восьми) байт. Ведь,
напомню, целые и вещественные числа и даты — это, в конечном счете, вещественное
число в Excel. Для себя я решение нашел — Fast Table Format. Но это уже не из
этой статьи…

Демо-Проект — SampleExcel3 (в архиве с данной
статьёй).

Часть 7: Пример обмена данными с Excel используя VCL и OLE.

Автор: Bird Feniks.

VCL.

В Delphi 5 и выше, для обмена данными между Вашим приложением
и Excel можно использовать компонент TExcelApplication, доступный на Servers
Page в Component Palette.

Создаем новый проект. На форму кладем TStringGrid, заполняем
его некоторыми данными и добавляем две кнопки, с названиями «To Excel» и «From
Excel». Так же на форму кладем компонент TExcelApplication и в свойстве «Name»
указываем «XLApp», а свойство «ConnectKind» меняем на «ckNewInstance».

Когда нам необходимо работать с Excel, то обычно мы открываем
ExcelApplication, затем открываем WorkBook и в конце используем WorkSheet.

Итак, несомненный интерес представляет для нас листы
(WorkSheets) в книге (WorkBook). Давайте посмотрим как всё это работает.

Посылка данных в Excel.

Это можно сделать с помощью следующей процедуры :

procedure TForm1.BitBtnToExcelOnClick(Sender: TObject); 
var
WorkBk : _WorkBook; // определяем WorkBook
WorkSheet : _WorkSheet; // определяем WorkSheet
I, J, K, R, C : Integer;
IIndex : OleVariant;
TabGrid : Variant;
begin
if GenericStringGrid.Cells[0,1] <> '' then
begin
IIndex := 1;
R := GenericStringGrid.RowCount;
C := GenericStringGrid.ColCount;
// Создаём массив-матрицу
TabGrid := VarArrayCreate([0,(R - 1),0,(C - 1)],VarOleStr);
I := 0;
// Определяем цикл для заполнения массива-матрицы 
repeat
for J := 0 to (C - 1) do
TabGrid[I,J] := GenericStringGrid.Cells[J,I];
Inc(I,1);
until 
I > (R - 1); 
// Соединяемся с сервером TExcelApplication
XLApp.Connect; 
// Добавляем WorkBooks в ExcelApplication 
XLApp.WorkBooks.Add(xlWBatWorkSheet,0); 
// Выбираем первую WorkBook 
WorkBk := XLApp.WorkBooks.Item[IIndex]; 
// Определяем первый WorkSheet 
WorkSheet := WorkBk.WorkSheets.Get_Item(1) as _WorkSheet; 
// Сопоставляем Delphi массив-матрицу с матрицей в WorkSheet 
Worksheet.Range['A1',Worksheet.Cells.Item[R,C]].Value := TabGrid; 
// Заполняем свойства WorkSheet
WorkSheet.Name := 'Customers'; 
Worksheet.Columns.Font.Bold := True; 
Worksheet.Columns.HorizontalAlignment := xlRight; 
WorkSheet.Columns.ColumnWidth := 14;
// Заполняем всю первую колонку 
WorkSheet.Range['A' + IntToStr(1),'A' + IntToStr(R)].Font.Color := clBlue;
WorkSheet.Range['A' + IntToStr(1),'A' + IntToStr(R)].HorizontalAlignment := xlHAlignLeft;
WorkSheet.Range['A' + IntToStr(1),'A' + IntToStr(R)].ColumnWidth := 31; 
// Показываем Excel
XLApp.Visible[0] := True;
// Разрываем связь с сервером
XLApp.Disconnect;
// Unassign the Delphi Variant Matrix 
TabGrid := Unassigned;
end; 
end;

Получение данных из Excel.

Это можно сделать с помощью следующей процедуры :

procedure TForm1.BitBtnFromExcelOnClick(Sender: TObject);
var 
WorkBk : _WorkBook; 
WorkSheet : _WorkSheet; 
K, R, X, Y : Integer; 
IIndex : OleVariant; 
RangeMatrix : Variant; 
NomFich : WideString; 
begin
NomFich := 'C:MyDirectoryNameOfFile.xls'; 
IIndex := 1;
XLApp.Connect; 
// Открываем файл Excel
XLApp.WorkBooks.Open(NomFich,EmptyParam,EmptyParam,EmptyParam,EmptyParam, 
EmptyParam,EmptyParam,EmptyParam,EmptyParam,
EmptyParam,EmptyParam, 
EmptyParam,EmptyParam,0); 
WorkBk := XLApp.WorkBooks.Item[IIndex];
WorkSheet := WorkBk.WorkSheets.Get_Item(1) as _WorkSheet; 
// Чтобы знать размер листа (WorkSheet), т.е. количество строк и количество 
// столбцов, мы активируем его последнюю непустую ячейку
WorkSheet.Cells.SpecialCells(xlCellTypeLastCell,EmptyParam).Activate; 
// Получаем значение последней строки
X := XLApp.ActiveCell.Row; 
// Получаем значение последней колонки
Y := XLApp.ActiveCell.Column; 
// Определяем количество колонок в TStringGrid
GenericStringGrid.ColCount := Y; 
// Сопоставляем матрицу WorkSheet с нашей Delphi матрицей
RangeMatrix := XLApp.Range['A1',XLApp.Cells.Item[X,Y]].Value; 
// Выходим из Excel и отсоединяемся от сервера 
XLApp.Quit; 
XLApp.Disconnect; 
// Определяем цикл для заполнения TStringGrid 
K := 1; 
repeat 
for R := 1 to Y do 
GenericStringGrid.Cells[(R - 1),(K - 1)] := RangeMatrix[K,R]; 
Inc(K,1); 
GenericStringGrid.RowCount := K + 1; 
until 
K > X;
// Unassign the Delphi Variant Matrix 
RangeMatrix := Unassigned; 
end;
OLE.

Ниже представлен пример создания новой таблицы в Excel 2000:

uses
ComObj, ActiveX;
var
Row, Col: integer;
DestRange: OleVariant;
Excel: Variant;
begin
Excel := CreateOleObject('Excel.Application.9');
Excel.Visible := True;
Excel.WorkBooks.Add; //Создать новую таблицу
//Можно помещать текст и значения в диапазон ячеек
//Поместить слово тест в диапазон ячеек
Excel.ActiveSheet.Range['A2', 'B3'].Value := 'Тест';
//Или число
Excel.ActiveSheet.Range['A4', 'B5'].Value := 42;
//А вот так задаётся формула
Excel.ActiveSheet.Range['A10', 'A11'].Formula := '=RAND()';
//Можно задавать номера ячеек и столбцов
Excel.ActiveSheet.Cells.Item[1, 1].Value := 'Первая ячейка';
Row:=1;
Col:=3;
Excel.ActiveSheet.Cells.Item[Row, Col].Value := 'Другая ячейка';
//Можно скопировать данный из одного диапазона ячеек в другой
DestRange := Excel.Range['D6', 'F10'];
Excel.Range['A1', 'C5'].Copy(DestRange);
//Можно задавать параметры шрифта в определённой ячейке
Excel.Range['A2', 'A2'].Font.Size := 20;
Excel.Range['A2', 'A2'].Font.FontStyle := 'Bold';
Excel.Range['A2', 'A2'].Font.Color := clFuchsia;
Excel.Range['A2', 'A2'].Font.Name := 'Arial';
//Можно ещё и так изменить цвет диапазона ячеек
Excel.Range['B2', 'C6'].Interior.Color := RGB(223, 123, 123);
end;

Далее представлен пример открытия и закрытия таблицы:

uses
ComObj, ActiveX;
var
Excel: Variant;
WBk : OleVariant;
SaveChanges: OleVariant;
begin
Excel := CreateOleObject('Excel.Application.9');
Excel.Visible := True;
//Открыть существующую таблицу
WBk := Excel.WorkBooks.Open('C:Test.xls');
...
WBk.Close(SaveChanges := True);
Excel.Quit;
end; 

>
Вставка формулы в Excel

  • Подписаться на тему
  • Сообщить другу
  • Скачать/распечатать тему



Сообщ.
#1

,
25.09.04, 17:40

    Full Member

    ***

    Рейтинг (т): 10

    Подскажите как вставить формулу в ячейку Excel.
    Пробовал так:

    ExpandedWrap disabled

      ASheetRef.Range[‘C19:C19′]:=’=СУММ(C6;C11;C14:C18)’;

    и вот так:

    ExpandedWrap disabled

      ASheetRef.Range[‘C19:C19′].Formula:=’=СУММ(C6;C11;C14:C18)’;

    И еще по всякому. Искал в интернете — ничего толкового не могу найти.

    Вылетает ошибка.

    И еще. Я в цикле (вернее в двух) перебираю ячейки и обрисовываю граници:

    ExpandedWrap disabled

          for i:=1 to PeriodCount + 2 do

          begin

              for j:=1 to INIT_ROW_COUNT do

              begin

                  ASheetRef.Cells[j,i].Borders[EDGE_TOP].LineStyle:=LINE_STYLE;

                  ASheetRef.Cells[j,i].Borders[EDGE_TOP].Weight:=LINE_WIDTH;

                  ASheetRef.Cells[j,i].Borders[EDGE_LEFT].LineStyle:=LINE_STYLE;

                  ASheetRef.Cells[j,i].Borders[EDGE_LEFT].Weight:=LINE_WIDTH;

                  ASheetRef.Cells[j,i].Borders[EDGE_BOTTOM].LineStyle:=LINE_STYLE;

                  ASheetRef.Cells[j,i].Borders[EDGE_BOTTOM].Weight:=LINE_WIDTH;

                  ASheetRef.Cells[j,i].Borders[EDGE_RIGHT].LineStyle:=LINE_STYLE;

                  ASheetRef.Cells[j,i].Borders[EDGE_RIGHT].Weight:=LINE_WIDTH;

              end;

          end;

    но все это происходит так меееееедленно. Нет ли способа ускорить процес?


    anika



    Сообщ.
    #2

    ,
    25.09.04, 22:51

      anika Newbie

      Рейтинг (т): 0

      По поводу второго могу порекомендовать убрать обновление экрана перед выполнением кода (_WordDoc как TWordDocument):

      ExpandedWrap disabled

        _WordDoc.Application.ScreenUpdating:=false;

      а самом конце обратно соответственно в true

      Добавлено 25.09.04, 23:07
      а формулу я присваивала как:

      ExpandedWrap disabled

        Sheet.Cells.Item[i,j].Value:=’=SUM(C6;C11;C14:C18)’


      Jureth



      Сообщ.
      #3

      ,
      27.09.04, 04:05

        Цитата rapido @ 26.09.04, 00:40

        И еще. Я в цикле (вернее в двух) перебираю ячейки и обрисовываю граници:

        ExpandedWrap disabled

              for i:=1 to PeriodCount + 2 do

              begin

                  for j:=1 to INIT_ROW_COUNT do

                  begin

                      ASheetRef.Cells[j,i].Borders[EDGE_TOP].LineStyle:=LINE_STYLE;

                      ASheetRef.Cells[j,i].Borders[EDGE_TOP].Weight:=LINE_WIDTH;

                      ASheetRef.Cells[j,i].Borders[EDGE_LEFT].LineStyle:=LINE_STYLE;

                      ASheetRef.Cells[j,i].Borders[EDGE_LEFT].Weight:=LINE_WIDTH;

                      ASheetRef.Cells[j,i].Borders[EDGE_BOTTOM].LineStyle:=LINE_STYLE;

                      ASheetRef.Cells[j,i].Borders[EDGE_BOTTOM].Weight:=LINE_WIDTH;

                      ASheetRef.Cells[j,i].Borders[EDGE_RIGHT].LineStyle:=LINE_STYLE;

                      ASheetRef.Cells[j,i].Borders[EDGE_RIGHT].Weight:=LINE_WIDTH;

                  end;

              end;

        У тебя приличную часть времени занимает доступ к ячейке таблицы, если запомнить этот адрес в переменной, то будет немного быстрее:

        ExpandedWrap disabled

          var a : OleVariant;//или какой он там?

          ..

              for i:=1 to PeriodCount + 2 do

              begin

                  for j:=1 to INIT_ROW_COUNT do

                  begin

                      a := ASheetRef.Cells[j,i];

                      a.Borders[EDGE_TOP].LineStyle:=LINE_STYLE;

                      a.Borders[EDGE_TOP].Weight:=LINE_WIDTH;

                      a.Borders[EDGE_LEFT].LineStyle:=LINE_STYLE;

                      a.Borders[EDGE_LEFT].Weight:=LINE_WIDTH;

                      a.Borders[EDGE_BOTTOM].LineStyle:=LINE_STYLE;

                      a.Borders[EDGE_BOTTOM].Weight:=LINE_WIDTH;

                      a.Borders[EDGE_RIGHT].LineStyle:=LINE_STYLE;

                      a.Borders[EDGE_RIGHT].Weight:=LINE_WIDTH;

                  end;

              end;

        Сообщение отредактировано: Jureth — 27.09.04, 04:31

        Wizard

        Bas



        Сообщ.
        #4

        ,
        27.09.04, 05:48

          Замни на FormulaR1C1 как это делает сам Excel

          ExpandedWrap disabled

            ActiveCell.FormulaR1C1 = «=VALUE(RC[-4])»


          rapido



          Сообщ.
          #5

          ,
          27.09.04, 16:52

            Full Member

            ***

            Рейтинг (т): 10

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

            Цитата anika, 26.09.04, 01:51

            По поводу второго могу порекомендовать убрать обновление экрана перед выполнением кода (_WordDoc как TWordDocument):

            _WordDoc.Application.ScreenUpdating:=false;

            а самом конце обратно соответственно в true

            Цитата Jureth, 27.09.04, 07:05

            У тебя приличную часть времени занимает доступ к ячейке таблицы, если запомнить этот адрес в переменной, то будет немного быстрее:

            Пробовал. Выигрыш незначительный.

            С формулами все равно не получается.
            При всех вариантах вылетает: OLE error 800A03EC

            ExpandedWrap disabled

                  ASheetRef.Cells[19,3]:=’=SUM(C6;C11;C14:C18)’;

                  ASheetRef.Range[‘C19:C19′].Formula:=’СУММ(C6;C11;C14:C18)’;

                  ASheetRef.Range[‘C19’, ‘C20′].Formula :=’=SUM(C6;C11;C14:C18)’;

                  ASheetRef.Cells.Item[19,3].Value:=’=SUM(C6;C11;C14:C18)’;

                  ASheetRef.Cells[19, 3].Formula:=’=SUM(C6;C11;C14:C18)’;

                  ASheetRef.Cells[19, 3].FormulaR1C1:=’=SUM(C6;C11;C14:C18)’;

            Может я чего-то недопонимаю?


            Jureth



            Сообщ.
            #6

            ,
            28.09.04, 02:31

              Цитата

              С формулами все равно не получается.

              Она скорее всего матюгается на ‘SUM’ — эту функцию она не понимает даже если её ввести руками (#ИМЯ?).

              Цитата

              Пробовал. Выигрыш незначительный.

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


              Jureth



              Сообщ.
              #7

              ,
              28.09.04, 05:15

                Этот вариант у меня сработал:

                ExpandedWrap disabled

                  aSheetRef.Cells[19,3].FormulaLocal:=’=СУММ(C6;C11;C14:C18)’;

                Процедуры, генерирующая строку:

                ExpandedWrap disabled

                  //Вспомогательная — генерирует буквенное представление столбца по его номеру

                  function GetCol(Col: integer): String;

                  begin

                    if Col<27 then

                      Result := Chr(Col+64)

                    else

                      Result := Chr((Col div 26)+64)+ Chr((Col mod 26)+64)

                  end;

                  //Возвращает строку типа ‘A1’ для одной ячейки

                  function CellsToRange(Row1, Col1: Integer): String; overload;

                  var

                    S : String;

                  begin

                    S := GetCol(Col1)+IntToStr(Row1);

                    Result := S;

                  end;

                  //Возвращает строку типа ‘A1:C5’ для диапазона (Row1, Col1 — TopLeft угол, Row2, Col2 — RightBottom)

                  function CellsToRange(Row1, Col1, Row2, Col2: Integer): String; overload;

                  var

                    S : String;

                  begin

                    S := GetCol(Col1)+IntToStr(Row1)+’:’+ GetCol(Col2)+ IntToStr(Row2);

                    Result := S;

                  end;

                юзается это примерно так:

                ExpandedWrap disabled

                    Sheet.Range[CellsToRange(1,1,15,15)].Borders[11].Weight := 2;

                    Sheet.Range[CellsToRange(1,1,15,15)].Borders[11].LineStyle := 4

                Пока всё.


                rapido



                Сообщ.
                #8

                ,
                28.09.04, 22:29

                  Full Member

                  ***

                  Рейтинг (т): 10

                  Ураааааа! Работает!
                  Сделал так:

                  ExpandedWrap disabled

                    procedure DrawCellBorders(var ASheetRef: Variant);

                    const

                        EDGE_LEFT      = 7;

                        EDGE_TOP       = 8;

                        EDGE_BOTTOM    = 9;

                        EDGE_RIGHT     = 10;

                        INNER_VERTICAL = 11;

                        INNER_HOR      = 12;

                        LINE_STYLE     = 1;

                        LINE_WIDTH     = 2;

                    begin

                        ASheetRef.Range[CellsToRange(1,1,86,PeriodCount + 2)].Borders[INNER_VERTICAL].Weight:=LINE_WIDTH;

                        ASheetRef.Range[CellsToRange(1,1,86,PeriodCount + 2)].Borders[INNER_VERTICAL].LineStyle:=LINE_STYLE;

                        ASheetRef.Range[CellsToRange(1,1,86,PeriodCount + 2)].Borders[INNER_HOR].Weight:=LINE_WIDTH;

                        ASheetRef.Range[CellsToRange(1,1,86,PeriodCount + 2)].Borders[INNER_HOR].LineStyle:=LINE_STYLE;

                        ASheetRef.Range[CellsToRange(1,1,86,PeriodCount + 2)].Borders[EDGE_TOP].Weight:=LINE_WIDTH;

                        ASheetRef.Range[CellsToRange(1,1,86,PeriodCount + 2)].Borders[EDGE_BOTTOM].LineStyle:=LINE_STYLE;

                        ASheetRef.Range[CellsToRange(1,1,86,PeriodCount + 2)].Borders[EDGE_LEFT].Weight:=LINE_WIDTH;

                        ASheetRef.Range[CellsToRange(1,1,86,PeriodCount + 2)].Borders[EDGE_RIGHT].LineStyle:=LINE_STYLE;

                    end;//DrawCellBorders

                  Прорисовывает почти мгновенно. Спасибо Jureth.

                  Формула тоже вставляется. Только есть небольшая проблема.
                  Как обновить значение в ячейке с автосумой? А то в ней прописывает 0. А у меня в сумируемых ячейках уже есть значения и их то и надо просумировать и показать пользователю.


                  Jureth



                  Сообщ.
                  #9

                  ,
                  29.09.04, 02:09

                    Попробуй Sheet.Calculate (или Range.Calculate) — он должен форсировать пересчет данных, но я не проверял.


                    rapido



                    Сообщ.
                    #10

                    ,
                    01.10.04, 13:44

                      Full Member

                      ***

                      Рейтинг (т): 10

                      Цитата Jureth, 29.09.04, 05:09

                      Попробуй Sheet.Calculate (или Range.Calculate) — он должен форсировать пересчет данных, но я не проверял.

                      Работает.

                      И еще два вопроса.
                      1. Как установить формат ячеек, то есть:

                      ExpandedWrap disabled

                        ASheetRef.Range[‘A1:A86′].NumberFormat:=’# ###0.0’;

                      2. И как присвоить имя книге:

                      ExpandedWrap disabled

                            ExcelApp:=CreateOleObject(‘Excel.Application’);

                            ExcelApp.Visible:=true;

                            WBRef:=ExcelApp.Workbooks.Add;

                            WBRef.Name:=’Some name’;

                      Вылетает ошибка и в первом и во втором случае. Искал в инете — ничего толкового не могу найти. У меня нету этой чертовой справки ВБ.


                      Jureth



                      Сообщ.
                      #11

                      ,
                      04.10.04, 02:46

                        1. Не знаю — не делал.
                        2. Это свойство — ReadOnly, установить его можно только при сохранении книги (WBRef.SaveAs)

                        Цитата

                        У меня нету этой чертовой справки ВБ

                        Переустановил бы Офис — ради разработки приложения можно и попотеть немного.


                        rapido



                        Сообщ.
                        #12

                        ,
                        04.10.04, 14:53

                          Full Member

                          ***

                          Рейтинг (т): 10

                          Понял. Еще раз спасибо.

                          Guru

                          Miscђka



                          Сообщ.
                          #13

                          ,
                          05.10.04, 02:12

                            Цитата Jureth, 4.10.04, 08:46

                            Переустановил бы Офис — ради разработки приложения можно и попотеть немного.

                            офис можно и доустановить, не удаляя его полностью :)


                            rapido



                            Сообщ.
                            #14

                            ,
                            06.10.04, 11:58

                              Full Member

                              ***

                              Рейтинг (т): 10

                              Вот так работает:

                              ExpandedWrap disabled

                                ASheetRef.Range[CellsToRange(5,3,45,PeriodCount + 2)].NumberFormat:=’# ###,0;(# ###,0);0,0′;

                                ASheetRef.Range[CellsToRange(50,3,86,PeriodCount + 2)].NumberFormat:=’# ###,0;(# ###,0);0,0′;

                              0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)

                              0 пользователей:

                              • Предыдущая тема
                              • Delphi: Общие вопросы
                              • Следующая тема

                              [ Script execution time: 0,0443 ]   [ 16 queries used ]   [ Generated: 13.04.23, 22:37 GMT ]  

                              Понравилась статья? Поделить с друзьями:
                            • Delicious meaning of the word
                            • Delphi excel createoleobject excel application
                            • Deleting words in excel
                            • Delphi excel borders linestyle
                            • Deleting spaces in word