Форум программистов, компьютерный форум, киберфорум
Delphi
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.60/43: Рейтинг темы: голосов - 43, средняя оценка - 4.60
0 / 0 / 0
Регистрация: 22.06.2011
Сообщений: 3
1

Как программно изменить CheckBox в файле Excel

22.06.2011, 16:22. Показов 7893. Ответов 16

Author24 — интернет-сервис помощи студентам
Помогите советом.
Весь инет облазил. Не могу найти ответ.

Выгружаю данные из Delphi в таблицу Excel:

Delphi
1
2
3
4
5
6
7
8
9
ExcelApp := CreateOleObject('Excel.Application');
Workbook := ExcelApp.WorkBooks.Open('aaa.xls',False);
// Запись значения в ячейку
ExcelApp.Range['L9','L9'].Value:=NomStr.Text;
 
Как менять CheckBox1 (который в Excel)?
По интуиции пробовал: 
ExcelApp.CheckBox1.value:=true;
ExcelApp.CheckBox1.Enabled:=true;
Но не работает.

Прочитал всю книгу Корнякова "Программирование документов и приложений MS Office в Delphi".
Разобрано все, кроме программирования "элементов управления".
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
22.06.2011, 16:22
Ответы с готовыми решениями:

Как программно в Excel изменить некоторые опции?
Как программно в Excel изменить следующие опции: 1. В меню Tools/Options/Security/Macro...

Как программно изменить тип данных в Excel?
Программа на VBasic возвращает из базы набор данных. В одной колонке данные типа Date. А...

Как программно изменить цвет ячейки и ширину столбцов в Excel
Здравствуйте, как можно программно изменить цвет ячейки в Excel? Я использую следующий код:...

Как изменить высоту строки в Excel-евском файле (модуль openpyxcl)
Друзья! import openpyxl wb = openpyxl.Workbook() ws = wb.active ...

16
13104 / 5885 / 1706
Регистрация: 19.09.2009
Сообщений: 8,808
23.06.2011, 09:59 2
На самом деле там всё по-хитрому. Элементы управления, которые можно добавить на лист Excel сами являются ActiveX элементами - т. е. OLE-объектами. Там реализован обобщённый подход - каждый такой элемент помещён в OLE-упаковку. И из этой OLE-упаковки доступ к элементу осуществляется через свойство Object.
Вот как можно работать с элементом типа CheckBox:
Delphi
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
procedure TForm1.Button1Click(Sender: TObject);
const
  //Имя файла рабочей книги Excel.
  Fn = 'Книга1.xls';
  //Имя чекбокса на листе рабочей книги Excel.
  chbName = 'CheckBox1';
var
  exApp, exBook, exSheet, Chb, Obj : Variant;
  FileName : String;
  i, Cnt : Integer;
begin
  //Полное имя файла рабочей книги. - Предполагается, что этот файл лежит
  //в той же папке, в которой расположен исполняемый файл программы.
  FileName := ExtractFilePath(ParamStr(0)) + Fn;
 
  exApp := CreateOleObject('Excel.Application');
  exApp.Visible := True;
  exBook := exApp.WorkBooks.Open(FileName);
 
  //Ссылка на первый лист в книге.
  exSheet := exBook.WorkSheets[1];
 
  //Ищем чекбокс на листе.
  Chb := Unassigned;
  Cnt := exSheet.OleObjects.Count;
  for i := 1 to Cnt do begin
    Obj := exSheet.OleObjects[i];
    if Obj.Name = chbName then begin
      Chb := Obj;
      Break;
    end;
  end;
  if TVarData(Chb).VDispatch = nil then begin
    ShowMessage('Чекбокс на листе не найден. Действие отменено.');
    Exit;
  end;
 
  ///Проверяем состояние чекбокса.
  if Chb.Object.Value then
    ShowMessage('Начальное состояние: чекбокс выбран.')
  else
    ShowMessage('Начальное состояние: чекбокс сброшен.')
  ;
  //Изменяем состояние чекбокса на противоположное.
  Chb.Object.Value := not Chb.Object.Value;
  ShowMessage('Теперь состояние чекбокса изменено.');
end;
Код осуществляющий поиск элемента на листе Excel можно оформить в виде отдельной функции.
---
Цитата Сообщение от Sharmon Посмотреть сообщение
Выгружаю данные из Delphi в таблицу Excel:
Delphi
1
2
3
4
ExcelApp := CreateOleObject('Excel.Application');
Workbook := ExcelApp.WorkBooks.Open('aaa.xls',False);
// Запись значения в ячейку
ExcelApp.Range['L9','L9'].Value:=NomStr.Text;
Sharmon, прежде чем записывать данные на лист Excel, надо получить ссылку на нужный лист. В этом коде этого не сделано.
1
0 / 0 / 0
Регистрация: 22.06.2011
Сообщений: 3
23.06.2011, 13:47  [ТС] 3
Спасибо огромное.

Делаю по приведенному коду. CheckBox-ы находит.
Меняет значения на противоположные.
Но почему-то в полученном экселевском файле, все равно не видно изменений.

Добавлено через 15 минут
Стал дальше разбираться. Почему-то независимо от состояния чекбокса,
всегда значение Chb.Object.Value равно true и не меняется
0
13104 / 5885 / 1706
Регистрация: 19.09.2009
Сообщений: 8,808
23.06.2011, 18:45 4
Лучший ответ Сообщение было отмечено как решение

Решение

Цитата Сообщение от Sharmon Посмотреть сообщение
Но почему-то в полученном экселевском файле, все равно не видно изменений.
Я сейчас посмотрел - да, интересные вещи там происходят. В общем, программа меняет значение чекбокса. Но как только происходит выход из процедуры, то сразу же все поля чекбокса устанавливаются в первоначальное состояние. Причём, если до выхода из процедуры сохранить рабочую книгу - тогда, как положено, книга сохранится с изменённым чекбоксом:
Вот этот код:
Delphi
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
uses
  ComObj;
 
procedure TForm1.Button1Click(Sender: TObject);
const
  //Имя файла рабочей книги Excel.
  Fn = 'Книга1.xls';
  //Имя чекбокса на листе рабочей книги Excel.
  chbName = 'CheckBox1';
var
  exApp, exBook, exSheet, Chb, Obj : Variant;
  FileName : String;
  i, Cnt : Integer;
  ChbState : Boolean;
begin
  //Полное имя файла рабочей книги. - Предполагается, что этот файл лежит
  //в той же папке, в которой расположен исполняемый файл программы.
  FileName := ExtractFilePath(ParamStr(0)) + Fn;
 
  exApp := CreateOleObject('Excel.Application');
  exApp.Visible := True;
  exBook := exApp.WorkBooks.Open(FileName);
 
  //Ссылка на первый лист в книге.
  exSheet := exBook.WorkSheets[1];
 
  //Ищем чекбокс на листе.
  Chb := Unassigned;
  Cnt := exSheet.OleObjects.Count;
  for i := 1 to Cnt do begin
    Obj := exSheet.OleObjects[i];
    if Obj.Name = chbName then begin
      Chb := Obj;
      Break;
    end;
  end;
  if TVarData(Chb).VDispatch = nil then begin
    ShowMessage('Чекбокс на листе не найден. Действие отменено.');
    Exit;
  end;
 
  ChbState := Chb.Object.Value;
  //Проверяем состояние чекбокса.
  if ChbState then
    ShowMessage('Начальное состояние: чекбокс выбран.')
  else
    ShowMessage('Начальное состояние: чекбокс сброшен.')
  ;
  //Изменяем состояние чекбокса на противоположное.
  Chb.Object.Value := not ChbState;
 
  ShowMessage('Теперь состояние чекбокса изменено.');
 
  //Сохранение раб. книги.
  exBook.Save;
end;
Я сначала подумал, что состояние чекбокса каким-то образом удерживается до момента отключения интерфейсов от объектов автоматизации. Обнуление ссылок на интерфейсы и их удаление, как раз происходит во время выхода из процедуры - когда уничтожаются локальные переменные. Чтобы это проверить, я разделил код на два метода - создание интерфейсов происходит в TForm1.Button1Click(), а уничтожение - в TForm1.Button2Click():
Delphi
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
uses
  ComObj;
 
var
  exApp, exBook, exSheet, Chb, Obj : Variant;
 
procedure TForm1.Button1Click(Sender: TObject);
const
  //Имя файла рабочей книги Excel.
  Fn = 'Книга1.xls';
  //Имя чекбокса на листе рабочей книги Excel.
  chbName = 'CheckBox1';
var
  //exApp, exBook, exSheet, Chb, Obj : Variant;
  FileName : String;
  i, Cnt : Integer;
  ChbState : Boolean;
begin
  //Полное имя файла рабочей книги. - Предполагается, что этот файл лежит
  //в той же папке, в которой расположен исполняемый файл программы.
  FileName := ExtractFilePath(ParamStr(0)) + Fn;
 
  exApp := CreateOleObject('Excel.Application');
  exApp.Visible := True;
  exBook := exApp.WorkBooks.Open(FileName);
 
  //Ссылка на первый лист в книге.
  exSheet := exBook.WorkSheets[1];
 
  //Ищем чекбокс на листе.
  Chb := Unassigned;
  Cnt := exSheet.OleObjects.Count;
  for i := 1 to Cnt do begin
    Obj := exSheet.OleObjects[i];
    if Obj.Name = chbName then begin
      Chb := Obj;
      Break;
    end;
  end;
  if TVarData(Chb).VDispatch = nil then begin
    ShowMessage('Чекбокс на листе не найден. Действие отменено.');
    Exit;
  end;
 
  ChbState := Chb.Object.Value;
  //Проверяем состояние чекбокса.
  if ChbState then
    ShowMessage('Начальное состояние: чекбокс выбран.')
  else
    ShowMessage('Начальное состояние: чекбокс сброшен.')
  ;
  //Изменяем состояние чекбокса на противоположное.
  Chb.Object.Value := not ChbState;
 
  ShowMessage('Теперь состояние чекбокса изменено.');
 
  //Сохранение раб. книги.
  //exBook.Save;
end;
 
procedure TForm1.Button2Click(Sender: TObject);
begin
  Obj := Unassigned;
  Chb := Unassigned;
  exSheet := Unassigned;
  exBook := Unassigned;
  exApp := Unassigned;
end;
Оказалось, что состояние чекбокса восстанавливается на первоначальное именно при выходе из метода TForm1.Button1Click(). Т. е. наличие интерфейсов непосредственно не влияет на удержание состояния чекбокса.
---
Попытка устанавливать состояние чекбокса по нескольку раз - не помогла. - Всё равно значение чекбокса устанавливается в первоначальное состояние при выходе из метода TForm1.Button1Click().
---
В общем, пока не ясно, почему так происходит.
---
А пока, возможно, положение может спасти то, что если сохранять книгу до окончания того метода, в котором изменяется состояние чекбокса, то изменённое состояние этого чекбокса всё же записывается в файл.
3
71 / 71 / 7
Регистрация: 19.07.2011
Сообщений: 357
19.07.2011, 02:11 5
Очень интересную тему тут затронули.
У меня почти патовая ситуация с этими чекбоксами.
Подрядился импортировать экселовские файлы в базу данных, но оказалось, что значения чекбоксов не импортируются. А там важная информация, в каком месте сломалась/погнулась/проржавела/и так далее трубка.
Не подскажете как обойти проблемку? Я подумал, если авторам темы удается обращаться к чекбоксам, то не подскажете как можно было бы записать где-нибудь ниже в подвале файла значение названия чекбокса и его значение в текстовом виде, чтобы при экспорте в CSV файл значение (1 или 0 или Yes / No) было видно.
данные в ескселовском файле в этом месте выглядят типа так:
....
Протерлась Верх Середина Низ
Проржавела Верх Середина Низ
....

эти три слова и есть form control объекты с чекбоксом (Верх Середина Низ), около каждого слова чекбокс, и в разных ситуациях либо тик либо пусто
Миниатюры
Как программно изменить CheckBox в файле Excel  
0
13104 / 5885 / 1706
Регистрация: 19.09.2009
Сообщений: 8,808
20.07.2011, 00:25 6
Можно сделать обход ЧекБоксов и прописать их значения прямо в те ячейки, над которыми они расположены. Координата по вертикали для ЧекБоксов задана в пунктах. По этому, по крайней мере, на какой строке расположен ЧекБокс - это определить можно. Но вот в каком он столбце - здесь пока не совсем ясно. - Какие единицы применены для исчисления координаты по горизонтали - непонятно. Например, горизонтальной координате в 183 пиксела (примерно 25.43 пункта), для ЧекБокса соответствует координата, равная 136.5 каких-то единиц. Что это за единицы - я пока не выяснил.
1
71 / 71 / 7
Регистрация: 19.07.2011
Сообщений: 357
25.07.2011, 22:08 7
спасибо за внимание к моему вопросу. очень надеюсь на то, что решение найдется.
0
0 / 0 / 0
Регистрация: 22.06.2011
Сообщений: 3
26.07.2011, 00:45  [ТС] 8
Я так и не смог добить эту тему и пришлось вовсе отказаться от чек-боксов в экселе.
Просто сделал квадратные ячейки и ставлю символ "Х" там где нужно. Благо я экспортирую в эксель, а не наоборот.
0
13104 / 5885 / 1706
Регистрация: 19.09.2009
Сообщений: 8,808
26.07.2011, 10:15 9
Ребята, есть идея в отношении ЧекБоксов.
У ЧекБокса есть свойство: LinkedCell. Если в это свойство записать адрес ячейки, то значение ЧекБокса будет выставляться по значению, которое записано в этой ячейке. Если в ячейку записать значение 0 (ноль) или "FALSE" ("ЛОЖЬ"), то ЧекБокс сбросится. Если в ячейку записать целочисленное значение, отличное от нуля, либо слово "TRUE" ("ИСТИНА"), то ЧекБокс установится (т. е., проставится галочка). Если значение в ячейке окажется нечисловым и отличным от слов "TRUE" или "FALSE" (для русского офиса также: "ИСТИНА" и "ЛОЖЬ"), тогда ЧекБокс будет установлен, но галочка будет показана бледным тоном.
Таким образом, можно управлять значением ЧекБокса через ячейку, которая связана с ним через свойство LinkedCell.
---
Можно даже сделать так. Например, нам надо поменять значения нескольких ЧекБоксов. Для этого достаточно выбрать одну ячейку и для каждого ЧекБокса проделать следующее:
1. Связываем ЧекБокс с ячейкой через свойство LinkedCell.
2. Через изменение значения в ячейке изменяем значение ЧекБокса.
3. Обнуляем свойство LinkedCell, тем самым отключая ЧекБокс от ячейки.
4. Повторяем пункты 1 - 3 для следующего ЧекБокса.
---
Мда, интересное поведение. Сейчас проверил с помощью такого кода:
Delphi
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
uses
  ComObj;
 
procedure TForm1.Button1Click(Sender: TObject);
const
  //Имя файла рабочей книги Excel.
  Fn = 'Книга1.xls';
  //Имя чекбокса на листе рабочей книги Excel.
  chbName = 'CheckBox1';
var
  exApp, exBook, exSheet, exCell, Chb, Obj : Variant;
  FileName : String;
  i, Cnt : Integer;
  ChbState : Boolean;
begin
  //Полное имя файла рабочей книги. - Предполагается, что этот файл лежит
  //в той же папке, в которой расположен исполняемый файл программы.
  FileName := ExtractFilePath(ParamStr(0)) + Fn;
 
  exApp := CreateOleObject('Excel.Application');
  exApp.Visible := True;
  exBook := exApp.WorkBooks.Open(FileName);
 
  //Ссылка на первый лист в книге.
  exSheet := exBook.WorkSheets[1];
 
  //Ищем чекбокс на листе.
  Chb := Unassigned;
  Cnt := exSheet.OleObjects.Count;
  for i := 1 to Cnt do begin
    Obj := exSheet.OleObjects[i];
    if Obj.Name = chbName then begin
      Chb := Obj;
      Break;
    end;
  end;
  if TVarData(Chb).VDispatch = nil then begin
    ShowMessage('Чекбокс на листе не найден. Действие отменено.');
    Exit;
  end;
 
  ChbState := Chb.Object.Value;
  //Проверяем состояние чекбокса.
  if ChbState then
    ShowMessage('Начальное состояние: чекбокс выбран.')
  else
    ShowMessage('Начальное состояние: чекбокс сброшен.')
  ;
  //Выбираем ячейку.
  exCell := exSheet.Cells[1, 1];
  //Записываем в ячейку значение, которое в дальнейшем поменяет значение чекбокса.
  if ChbState then exCell.Value := '0'
  else exCell.Value := '1';
  //Связываем чекбокс с ячейкой.
  Chb.Object.LinkedCell := exCell.Address;
  //Отключаем ЧекБокс от ячейки.
  Chb.Object.LinkedCell := '';
 
  ShowMessage('Теперь состояние чекбокса изменено.');
 
  //Сохранение раб. книги.
  //exBook.Save;
end;
При этом, в то время, когда ЧекБокс связан с ячейкой - его значение соответствует значению, которое записано в ячейке. Как только ЧекБокс отключается от ячейки, то происходит следующее:
- если ЧекБокс был изначально сброшенным и был затем установлен на галочку, то он возвращается в прежнее состояние.
- если ЧекБокс был изначально установленным и затем был сброшен, то возвращения в прежнее состояние не происходит.
Но! В любом случае, если потом сохранить файл - или программно или вручную, а затем открыть - то окажется, что значение ЧекБокса поменялось так, как было задумано в алгоритме.
1
71 / 71 / 7
Регистрация: 19.07.2011
Сообщений: 357
26.07.2011, 10:38 10
эх, блин, если бы мои чекбоскы были из категории доступных через VB код....
так ведь - нет, они у меня все из FormControl, у которых вообще никакой связи с ячейкой не высвечивается.
0
13104 / 5885 / 1706
Регистрация: 19.09.2009
Сообщений: 8,808
26.07.2011, 10:56 11
Я сейчас ещё поэкспериментировал. В общем, как я понял, даже если состояние ЧекБокса после программного изменения возвращается к прежнему - то это, на самом деле, только баг визуализации. Т. е., на самом деле, состояние ЧекБокса как положено поменялось, но его видимое представление может не соответствовать установленному значению.
В подтвержение можно поэкспериментировать с помощью этого кода:
Delphi
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
uses
  ComObj;
 
const
  //Имя чекбокса на листе рабочей книги Excel.
  chbName = 'CheckBox1';
var
  exApp, exBook, exSheet, exCell, Chb, Obj : Variant;
 
procedure TForm1.Button1Click(Sender: TObject);
const
  //Имя файла рабочей книги Excel.
  Fn = 'Книга1.xls';
var
  //exApp, exBook, exSheet, Chb, Obj : Variant;
  FileName : String;
  i, Cnt : Integer;
  ChbState : Boolean;
begin
  //Полное имя файла рабочей книги. - Предполагается, что этот файл лежит
  //в той же папке, в которой расположен исполняемый файл программы.
  FileName := ExtractFilePath(ParamStr(0)) + Fn;
 
  exApp := CreateOleObject('Excel.Application');
  exApp.Visible := True;
  exBook := exApp.WorkBooks.Open(FileName);
 
  //Ссылка на первый лист в книге.
  exSheet := exBook.WorkSheets[1];
 
  //Ищем чекбокс на листе.
  Chb := Unassigned;
  Cnt := exSheet.OleObjects.Count;
  for i := 1 to Cnt do begin
    Obj := exSheet.OleObjects[i];
    if Obj.Name = chbName then begin
      Chb := Obj;
      Break;
    end;
  end;
  if TVarData(Chb).VDispatch = nil then begin
    ShowMessage('Чекбокс на листе не найден. Действие отменено.');
    Exit;
  end;
 
  ChbState := Chb.Object.Value;
  //Проверяем состояние чекбокса.
  if ChbState then
    ShowMessage('Начальное состояние: чекбокс выбран.')
  else
    ShowMessage('Начальное состояние: чекбокс сброшен.')
  ;
 
  //(*
  //Выбираем ячейку.
  exCell := exSheet.Cells[1, 1];
  //Записываем в ячейку значение, которое в дальнейшем поменяет значение чекбокса.
  if ChbState then exCell.Value := '0'
  else exCell.Value := '1';
  //Связываем чекбокс с ячейкой.
  Chb.Object.LinkedCell := exCell.Address;
  //Отключаем ЧекБокс от ячейки.
  Chb.Object.LinkedCell := '';
 
  //(*
  //Проверяем состояние чекбокса.
  if ChbState = Chb.Object.Value then
    ShowMessage('Начальное состояние не изменилось.')
  else
    ShowMessage('Начальное состояние изменено.')
  ;
  //*)
 
  //Сохранение раб. книги.
  //exBook.Save;
end;
 
//Изменить.
procedure TForm1.Button2Click(Sender: TObject);
var
  exCell : Variant;
  ChbState : Boolean;
begin
  ChbState := Chb.Object.Value;
  //Выбираем ячейку.
  exCell := exSheet.Cells[1, 1];
  //Записываем в ячейку значение, которое в дальнейшем поменяет значение чекбокса.
  if ChbState then exCell.Value := '0'
  else exCell.Value := '1';
  //Связываем чекбокс с ячейкой.
  Chb.Object.LinkedCell := exCell.Address;
  //Отключаем ЧекБокс от ячейки.
  Chb.Object.LinkedCell := '';
end;
 
//Проверить.
procedure TForm1.Button3Click(Sender: TObject);
var
  ChbState : Boolean;
begin
  ChbState := Chb.Object.Value;
  //Проверяем состояние чекбокса.
  if ChbState then
    ShowMessage('Чекбокс выбран.')
  else
    ShowMessage('Чекбокс сброшен.')
  ;
end;
 
procedure TForm1.Button4Click(Sender: TObject);
begin
  Obj := Unassigned;
  Chb := Unassigned;
  exCell := Unassigned;
  exSheet := Unassigned;
  exBook := Unassigned;
  exApp := Unassigned;
end;
Всё работает правильно. Проблема только в визуализации. Причём, визуальное несоответствие пропадает при переоткрытии книги.
Вложения
Тип файла: rar CheckBoxOnTheExcelSheet.rar (187.8 Кб, 22 просмотров)
0
13104 / 5885 / 1706
Регистрация: 19.09.2009
Сообщений: 8,808
26.07.2011, 11:05 12
zremas, в твоём случае можно действовать подобным образом - все ЧекБоксы привязать к ячейкам и в эти ячейки записать значения, соответствующие состояниям ЧекБоксов. Как я уже писал ранее - в какой строке находится ЧекБокс - это определить можно. Но вот в каком он столбце - с этим не ясно пока. Тем не менее, можно попытаться сделать так - внизу листа программно создавать новую таблицу, куда записывать состояния ЧекБоксов. Правда, здесь нужно решить промежуточную задачу - раскладку чекбоксов по строкам и рядам.
0
71 / 71 / 7
Регистрация: 19.07.2011
Сообщений: 357
26.07.2011, 19:03 13
Пробовал запустить коды, публикуемые в обсуждении, насколько смог адаптировать код, они действуют на ActiveX -ные чекбоксы.
Был бы безумно рад, если бы удалось обратиться к "моим" чекбоксам из категории Form Control и вытащить номер строки и состояние.
Ниже оригинал xls с чекбоксами
Вложения
Тип файла: xls Checkboxes.xls (37.5 Кб, 34 просмотров)
0
13104 / 5885 / 1706
Регистрация: 19.09.2009
Сообщений: 8,808
27.07.2011, 11:20 14
zremas, доступ к таким ЧекБоксам осуществляется через коллекцию CheckBoxes.
Вот пример - программа может перебирать и читать свойства всех ЧекБоксов из коллекции CheckBoxes, а также перебирать и читать свойства всех OLE объектов, внедрённых на лист:
Delphi
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
uses
  ComObj;
 
var
  exApp, exBook, exSheet, Obj : Variant;
 
//Открыть книгу Excel.
procedure TForm1.Button1Click(Sender: TObject);
var
  Od : TOpenDialog;
begin
  Od := OpenDialog1;
  if Od.InitialDir = '' then Od.InitialDir := ExtractFilePath(ParamStr(0));
  if not Od.Execute then Exit;
  if not FileExists(Od.FileName) then begin
    MessageDlg(
      'Файл с заданным именем не найден. Действие отменено.'
      , mtWarning, [mbOK], 0
    );
    Exit;
  end;
 
  exApp := CreateOleObject('Excel.Application');
  exApp.Visible := True;
  exBook := exApp.WorkBooks.Open(Od.FileName);
 
  //Ссылка на первый лист в книге.
  exSheet := exBook.WorkSheets[1];
end;
 
//Собрать сведения о всех ЧекБоксах из коллекции CheckBoxes.
procedure TForm1.Button2Click(Sender: TObject);
var
  i, Cnt : Integer;
begin
  Cnt := exSheet.CheckBoxes.Count;
  Memo1.Lines.Add('Всего элементов в коллекции CheckBoxes: ' + IntToStr(Cnt));
  Memo1.Lines.Add('Перечень:');
  for i := 1 to Cnt do begin
    Obj := exSheet.CheckBoxes[i];
    Memo1.Lines.Add(
      IntToStr(i) + ': Name = "' + Obj.Name + '", ' + #9 + 'Text = "' + Obj.Text + '",'
       + #9 + 'Value = "' + IntToStr(Obj.Value) + '".'
    );
  end;
end;
 
//Собрать сведения о всех OLE объектах, которые внедрены на лист Excel.
procedure TForm1.Button3Click(Sender: TObject);
var
  i, Cnt : Integer;
  S : String;
begin
  Cnt := exSheet.OLEObjects.Count;
  Memo1.Lines.Add('Всего OLE объектов: ' + IntToStr(Cnt));
  Memo1.Lines.Add('Перечень:');
  for i := 1 to Cnt do begin
    Obj := exSheet.OLEObjects[i];
    S := IntToStr(i) + ': Name = "' + Obj.Name + '",'
      + #9 + 'Object.Caption = "' + Obj.Object.Caption + '"'
    ;
    try
      S := S + ',' + #9 + 'Object.Value = "' + IntToStr(Obj.Object.Value) + '".'
    finally
    end;
    Memo1.Lines.Add(S);
  end;
end;
 
//Отключиться от интерфейсов OLE-автоматизации.
procedure TForm1.Button4Click(Sender: TObject);
begin
  Obj := Unassigned;
  exSheet := Unassigned;
  exBook := Unassigned;
  exApp := Unassigned;
end;
Цитата Сообщение от zremas Посмотреть сообщение
и вытащить номер строки
Номер строки можно определить. Вечером посмотрю.
Миниатюры
Как программно изменить CheckBox в файле Excel  
Вложения
Тип файла: rar CheckBoxOnTheExcelSheet-02.rar (201.1 Кб, 20 просмотров)
1
71 / 71 / 7
Регистрация: 19.07.2011
Сообщений: 357
27.07.2011, 20:31 15
Попробовал код. Работает like a charm!
Заметил, что значение чекнутого OLE объекта она показывает как "-1". Это что, особенность эксела, хранящего такие значения?
FormControl checkbox дает значение "1"

вот результат обработки файла evaluation.xls
Total FormControl CheckBoxes: 28
List:
1: Name = "Check Box 2", Text = "RERAN", Value = "-4146".
2: Name = "Check Box 3", Text = "DISCARDED", Value = "1".
3: Name = "Check Box 4", Text = "STOCKED", Value = "-4146".
4: Name = "Check Box 5", Text = "RECHROMED", Value = "-4146".
5: Name = "Check Box 6", Text = "RERAN", Value = "-4146".
6: Name = "Check Box 7", Text = "DISCARDED", Value = "1".
7: Name = "Check Box 8", Text = "STOCKED", Value = "-4146".
8: Name = "Check Box 9", Text = "WAS NOT PULLED", Value = "-4146".
9: Name = "Check Box 10", Text = "GOOD", Value = "-4146".
10: Name = "Check Box 11", Text = "ABRASION", Value = "1".
11: Name = "Check Box 13", Text = "BASE METAL WEAR", Value = "1".
12: Name = "Check Box 17", Text = "HEAT CRACKS", Value = "-4146".
13: Name = "Check Box 19", Text = "FLUID WASH", Value = "-4146".
14: Name = "Check Box 46", Text = "GENERAL WEAR", Value = "-4146".
15: Name = "Check Box 47", Text = "GOOD", Value = "-4146".
16: Name = "Check Box 48", Text = "ABRASION", Value = "1".
17: Name = "Check Box 49", Text = "TORN ELASTOMER", Value = "-4146".
18: Name = "Check Box 50", Text = "PUMPED OFF", Value = "-4146".
19: Name = "Check Box 52", Text = "GENERAL WEAR", Value = "1".
20: Name = "Check Box 54", Text = "SWOLLEN", Value = "-4146".
21: Name = "Check Box 56", Text = "BURNT/HARD/CRACKED", Value = "-4146".
22: Name = "Check Box 57", Text = "FLUID WASH", Value = "-4146".
23: Name = "Check Box 60", Text = "NO WEAR", Value = "-4146".
24: Name = "Check Box 61", Text = "NORMAL WEAR", Value = "-4146".
25: Name = "Check Box 62", Text = "MINOR WEAR", Value = "-4146".
26: Name = "Check Box 63", Text = "MAJOR WEAR", Value = "-4146".
27: Name = "Check Box 64", Text = "GONE", Value = "-4146".
28: Name = "Check Box 66", Text = "CORRODED", Value = "1".

Да, осталось научиться узнавать номер строки и колонки и можно считатывать значения.

А как узнать какие Methods доступны для exSheet.CheckBoxes[i]

поробовал mycolumn:=exSheet.CheckBoxes[i].Column; грит нет такого метода

Добавлено через 18 минут
если нет такого прямого метода по определению колонки и строки, то может есть какой-то способ узнавать абсолютную позицию слова или чекбокса на канве, типа в единицах измерения файла, то есть я имею ввиду следующее решение, мне же надо просто раздраконить группу чекбоксов на левую и правую области:
поскольку группы чекбоксов, принадлежащих STATOR находятся в геометрической области под STATOR, а номерация checkbox идет слева-направо (невзирая на лица ), то найти "типа" некий вертикальный параметр слова STATOR и сравнивать такой же вертикальный параметр у чекбоксов, если он больше или равен STATOR-овскому, то это чекбокс от семейства STATOR ... и так далее
0
13104 / 5885 / 1706
Регистрация: 19.09.2009
Сообщений: 8,808
27.07.2011, 21:47 16
Удалось определить строку и столбец, в которых расположен любой ЧекБокс (из коллекции CheckBoxes или OLE-объект, внедрённый на лист Excel).
Код:
Delphi
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
uses
  ComObj;
 
var
  exApp, exBook, exSheet, exObj : Variant;
 
//Определение номера строки, на которой расположена горизонтальная ось объекта.
function GetRowNum(const aExSheet, aExObj : Variant) : Integer;
var
  Height, Y : Extended;
begin
  Result := 0;
  Height := 0;
  //Вертикальная координата горизонтальной оси объекта, выраженная в пунктах (Points).
  Y := aExObj.Top + aExObj.Height / 2;
  repeat
    Result := Result + 1;
    Height := Height + aExSheet.Rows[Result].Height;
  until Height >= Y;
end;
 
//Определение номера столбца, на котором расположен левый край объекта.
function GetColNum(const aExSheet, aExObj : Variant) : Integer;
var
  Width, X : Extended;
begin
  Result := 0;
  Width := 0;
  //Горизонтальная координата левого края объекта, выраженная в пунктах (Points).
  X := aExObj.Left;
  repeat
    Result := Result + 1;
    Width := Width + aExSheet.Columns[Result].Width;
  until Width >= X;
end;
 
//Открыть книгу Excel.
procedure TForm1.Button1Click(Sender: TObject);
var
  Od : TOpenDialog;
begin
  Od := OpenDialog1;
  if Od.InitialDir = '' then Od.InitialDir := ExtractFilePath(ParamStr(0));
  if not Od.Execute then Exit;
  if not FileExists(Od.FileName) then begin
    MessageDlg(
      'Файл с заданным именем не найден. Действие отменено.'
      , mtWarning, [mbOK], 0
    );
    Exit;
  end;
 
  exApp := CreateOleObject('Excel.Application');
  exApp.Visible := True;
  exBook := exApp.WorkBooks.Open(Od.FileName);
 
  //Ссылка на первый лист в книге.
  exSheet := exBook.WorkSheets[1];
end;
 
//Собрать сведения о всех ЧекБоксах из коллекции CheckBoxes.
procedure TForm1.Button2Click(Sender: TObject);
var
  i, Cnt, Row, Col : Integer;
begin
  Cnt := exSheet.CheckBoxes.Count;
  Memo1.Lines.Add('--------------------------------------------------');
  Memo1.Lines.Add('Всего элементов в коллекции CheckBoxes: ' + IntToStr(Cnt));
  Memo1.Lines.Add('Перечень:');
  for i := 1 to Cnt do begin
    exObj := exSheet.CheckBoxes[i];
    Row := GetRowNum(exSheet, exObj);
    Col := GetColNum(exSheet, exObj);
    Memo1.Lines.Add(IntToStr(i) + ':');
    Memo1.Lines.Add('  Name = "' + exObj.Name + '"');
    Memo1.Lines.Add('  Text = "' + exObj.Text + '"');
    Memo1.Lines.Add('  Value = "' + IntToStr(exObj.Value) + '"');
    Memo1.Lines.Add('  Row = "' + IntToStr(Row) + '"');
    Memo1.Lines.Add('  Col = "' + IntToStr(Col) + '"');
  end;
end;
 
//Собрать сведения о всех OLE объектах, которые внедрены на лист Excel.
procedure TForm1.Button3Click(Sender: TObject);
var
  i, Cnt, Row, Col : Integer;
begin
  Cnt := exSheet.OLEObjects.Count;
  Memo1.Lines.Add('--------------------------------------------------');
  Memo1.Lines.Add('Всего OLE объектов: ' + IntToStr(Cnt));
  Memo1.Lines.Add('Перечень:');
  for i := 1 to Cnt do begin
    exObj := exSheet.OLEObjects[i];
    Row := GetRowNum(exSheet, exObj);
    Col := GetColNum(exSheet, exObj);
    Memo1.Lines.Add(IntToStr(i) + ':');
    Memo1.Lines.Add('  Name = "' + exObj.Name + '"');
    Memo1.Lines.Add('  Object.Caption = "' + exObj.Object.Caption + '"');
    try
      Memo1.Lines.Add('  Object.Value = "' + IntToStr(exObj.Object.Value) + '"');
    finally
    end;
    Memo1.Lines.Add('  Row = "' + IntToStr(Row) + '"');
    Memo1.Lines.Add('  Col = "' + IntToStr(Col) + '"');
  end;
end;
 
//Отключиться от интерфейсов OLE-автоматизации.
procedure TForm1.Button4Click(Sender: TObject);
begin
  exObj := Unassigned;
  exSheet := Unassigned;
  exBook := Unassigned;
  exApp := Unassigned;
end;
Цитата Сообщение от zremas Посмотреть сообщение
Заметил, что значение чекнутого OLE объекта она показывает как "-1". Это что, особенность эксела, хранящего такие значения?
Там по разному представлены значения ЧекБоксов.
Для OLE ЧекБоксов (Microsoft Forms 2.0 CheckBox):
Если такой ЧекБокс выбран, то Object.Value = -1. Вернее любое значение Object.Value <> 0 воспринимается, как установленное (TRUE). Если Object.Value = 0, то это соответствует сброшенному ЧекБоксу (значение FALSE). - Это стандартные правила, принятые для логических значений в Windows, в Си и в Delphi.
А для тех ЧекБоксов, которые принадлежат коллекции CheckBoxes, судя по логам - если такой ЧекБокс выбран, то значение Value = 1, если сброшен, то Value = -4146.
Получается, здесь установленному состоянию (TRUE) соответствует 1, а сброшенному соответствует Value <> 1. Что касается Value <> 1 для сброшенного состояния - это можно уточнить путём экспериментов.
---
В приложенном архиве проект Delphi, файлы Excel и файл с текстом модуля на VBA. В модуле VBA реализован код с функциональностью похожей на ту, что реализована в проекте Delphi. Это сделано для того, чтобы прямо в Excel можно было выполнять проверки.
Модуль VBA:
Visual Basic
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
Option Explicit
 
Sub sub1()
  Dim exSheet As Excel.Worksheet
  Dim exObj As Object
  Dim Row As Long
  Dim Height As Double
  Dim Y As Double
  Dim Col As Long
  Dim Width As Double
  Dim X As Double
  
  Set exSheet = Application.ActiveSheet
  'Перечень объектов из коллекции CheckBoxes.
  Debug.Print "Перечень объектов из коллекции CheckBoxes:"
  For Each exObj In exSheet.CheckBoxes
    'Определяем номер строки, на которой расположена горизонтальная ось объекта.
    Row = 0
    Height = 0
    'Вертикальная координата горизонтальной оси объекта, выраженная в пунктах (Points).
    Y = exObj.Top + exObj.Height / 2
    Do
      Row = Row + 1
      Height = Height + exSheet.Rows(Row).Height
    Loop While Height < Y
    
    'Определяем номер столбца, на котором расположен левый край объекта.
    Col = 0
    Width = 0
    'Горизонтальная координата левого края объекта, выраженная в пунктах (Points).
    X = exObj.Left
    Do
      Col = Col + 1
      Width = Width + exSheet.Columns(Col).Width
    Loop While Width < X
    
    'MsgBox ...
    Debug.Print "Name = """ & exObj.Name & """, Text = """ & exObj.Text & """" _
      & Chr(10) & "  Value = """ & exObj.Value & """" _
      & Chr(10) & "  Row = """ & Row & """, Col = """ & Col & """."
  Next exObj
End Sub
 
Sub sub2()
  Dim exSheet As Excel.Worksheet
  Dim exObj As OLEObject
  Dim Row As Long
  Dim Height As Double
  Dim Y As Double
  Dim Col As Long
  Dim Width As Double
  Dim X As Double
  
  Set exSheet = Application.ActiveSheet
  'Перечень OLE объектов.
  Debug.Print "Перечень OLE объектов:"
  For Each exObj In exSheet.OLEObjects
    'Определяем номер строки, на которой расположена горизонтальная ось объекта.
    Row = 0
    Height = 0
    'Вертикальная координата горизонтальной оси объекта, выраженная в пунктах (Points).
    Y = exObj.Top + exObj.Height / 2
    Do
      Row = Row + 1
      Height = Height + exSheet.Rows(Row).Height
    Loop While Height < Y
    
    'Определяем номер столбца, на котором расположен левый край объекта.
    Col = 0
    Width = 0
    'Горизонтальная координата левого края объекта, выраженная в пунктах (Points).
    X = exObj.Left
    Do
      Col = Col + 1
      Width = Width + exSheet.Columns(Col).Width
    Loop While Width < X
    
    'MsgBox ...
    Debug.Print "Name = """ & exObj.Name & """, Object.Caption = """ & exObj.Object.Caption & """" _
      & Chr(10) & "  Object.Value = """ & exObj.Object.Value & """" _
      & Chr(10) & "  Row = """ & Row & """, Col = """ & Col & """."
  Next exObj
End Sub
Этот модуль присоединён к файлам Excel.
Миниатюры
Как программно изменить CheckBox в файле Excel  
Вложения
Тип файла: rar CheckBoxOnTheExcelSheet-03.rar (207.3 Кб, 40 просмотров)
1
71 / 71 / 7
Регистрация: 19.07.2011
Сообщений: 357
27.07.2011, 22:28 17
оба-на! с меня ящик пива! Я серьезно!
смотри в личке

---
Mawrat: Спасибо. Но оплаты не нужно.
0
27.07.2011, 22:28
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
27.07.2011, 22:28
Помогаю со студенческими работами здесь

CheckBox.Location программно создаваемых CheckBox - расположить их в столбик
Цель-разместить на форме определенное количество чекбоксов - что благополучно достигнуто; и...

Изменение программно созданных TextBox по событию программно созданного CheckBox
Помогите пожалуйста! мне нужно разрешить изменение полей всех TextBox и разрешить нажимать на...

Как программно поставить флажок в checkBox?
Как программно поставить флажок в checkBox?

Как получить значение из Checkbox созданного программно?
Создано программно несколько чекбоксов. Как можно получить из них значение? Id у них нет. Когда...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru