Delphi excel сортировка по столбцу

Обновлено: 06.07.2024

I am writing a program in Delphi 10/Seattle to control Excel 2013. I need to do a sort based on a column. The column has headers. While my code compiles, the actual SORT command gives the error 'Could not convert variant of type (Error) into type (Boolean).' In short, I have a parameter wrong, but I can't determine WHICH parameter. I have gone through the MS syntax (URL listed below), but can't find anything wrong. Here is a working sample which shows the problem. I DID generate my own type library, which is in the USES clause.

3,012 4 4 gold badges 31 31 silver badges 72 72 bronze badges Maybe this can help: In excel start recording a macro, than do your sorting. Now you can look in the macro exactly how the command should look like. I always found this much simple and more accurate than MS help @Sertac - The ONLY way I can get this to work is by defining both ranges as OleVariants. Please submit your comment as an answer, and I will accept.

2 Answers 2

There are more than one offending parameters. The thing what is wrong with them is they don't like EmptyParam , although it is what we should be passing for an unused optional parameter.

It is difficult to locate which one(s) because of two reasons. One is that, the way you supply parameters works quite alright when you use late binding. The other one is the misleading error message:

. EVariantTypeCastError with message 'Could not convert variant of type (Error) into type (Boolean)'.

An EmptyParam is a variant set to type varError , so first part suggests that we should suspect EmptyParam s. Conversion to boolean fails, then what we'll be looking for is an EmptyParam passed for an optional boolean parameter. Unfortunately there are none, not even anything boolean-like. In fact any one of the 'DataOption' enumerations cause the above error message.

Here is a possible systematic approach that might help to find a working solution:

  • Use late binding first, pass as little parameters as required.
  • Fill all remaining parameters with EmptyParam , test, then adapt the call to early binding.
  • From right to left, replace unused optional parameters with actual values until you get a different error, or make it work.

Here is my working sample:

Finally I'm glad that Type parameter did not complain passing an EmptyParam because I don't understand what it is.

Old answer follows:

I tested your parameters by using the IDispatch/Invoke route, late binding, it generally has a higher probability of getting to work despite loosing some performance and type safety. None of them are wrong, I also tested other keys. Although parameters are not wrong, excel throws an error if early binding is used. Here is one working example:

Обработка Excel, сортировка столбцов - 08.06.2009, 12:28

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

1) пишешь макрос на VBA.
2) переписываешь его на Дельфи.

1) пишешь макрос на VBA.
2) переписываешь его на Дельфи.

Да да. Както так. Сам сталкивался.
Ещё один совет. Если нужно сделать что-то, то сначала "Сервис->Макрос->Начать запись". Выполняешь действия, останавливаешь макрос. Затем просматриваешь код макроса и отделяешь зёрна от плевел. Так можно очень много вытащить. Главное понять принцип. Например многое делается с объектом Range. Даже если нужно выполнять действия над одной ячейкой. Что интересно - есть объект Selection - то, что выбрано в Range. Так, чтобы, например, ячейки B1:C2 слить и установить выравнивание по центру, нужно сначала выбрать их
Sheet.Range['B1:C2'].Select;
а затем действия выполнять
Exl.Selection.Merge;
Exl.Selection.HorizontalAlignment := xlCenter;
где

Не забываем при переносе из VBA заменять скобки массивов на квадратные, кавычки - на одинарные.

Так, чтобы, например, ячейки B1:C2 слить и установить выравнивание по центру, нужно сначала выбрать их
Sheet.Range['B1:C2'].Select;
а затем действия выполнять
Exl.Selection.Merge;

Вообще-то выбор группы ячеек не является обязательным условием. Можно так..

Репутация: нет
Всего: нет

Репутация: нет
Всего: нет

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

Репутация: 1
Всего: 27

В StringGride есть свойство Index наверно это то что тебе надо

Репутация: нет
Всего: нет

не знаю, что вы имели ввиду, но свойства Индекс у СтрингГрида нет, если вы хотели мне сказать, что менять значения надо по соответствующим индексам, то я догодался и сам об этом, только у меня не выходит грамотно это прописать, поэтому я и обратился за помощью

Репутация: 1
Всего: 27

Я по твоему образу написала код но он ругается на StringGrid1Sells[i-1,0];
наверно потому что String не заполнен.

Репутация: 53
Всего: 133

нет. Потому что нужна точка и не правильно написано.

Если хочешь, что бы что-то работало - используй написанное,
если хочешь что-то понять - пиши сам.

Репутация: нет
Всего: 1

Staruha, за StringGrid1Sells, особенно за Sells ))

"ол рихтс!"- сказал студент-самоучка, изучающий английский язык, положив на стол газету "невс тимес"

Репутация: нет
Всего: нет

по существу ответа так и не было, больше ни у кого никаких мыслей нет?

Репутация: 53
Всего: 133

Можно либо делать сортировку в ручную, запихивая всю таблицу в многомерный массив, либо использовать другой компонент. К примеру, VirtualStringTree.
Если хочешь, что бы что-то работало - используй написанное,
если хочешь что-то понять - пиши сам.

Репутация: 1
Всего: 27

MerCus нам немножко осталось до правильного решения.Я в коде все исправила больше не ругается только опять не могу тестировать.Вопрос Что в String данные тоже программно вводить?Чейто я не найду там ReadOnly

Репутация: 1
Всего: 27

OPtions.goEditing люди добрые подсказали.

Сейчас че-нить накопаю

Репутация: 1
Всего: 27

Репутация: 65
Всего: 372

Что то подобное:

Сортирует СТРОКИ, а не числа, которые взяты просто для примера

Репутация: нет
Всего: нет

Staruha вы сортируете один столбец! это проще простого, а мне надо один столбец сортировать по возрастанию, а все остальные по этому столбцу.
THandle спасибо, но тоже не совсем то.

Репутация: 1
Всего: 27

Цитата

Сортирует СТРОКИ, а не числа, которые взяты просто для примера

Я сама поражаюсь как это происходит ,но Строка в мною приведенном коде сортируется Супер ,а именно по первой букве ,по второй,третьей и т.д.

Цитата

Staruha вы сортируете один столбец! это проще простого

спасибо тебе MerCus

так что получается,если Stroka:=StringGrid1.Cells[1,k]+StringGrid1.Cells[2,k]+. ;
тоже должна сортироваться по тому же принципу. А массив или String(ты сам просил,хотя во всех примерах сортируются массивы) это просто контейнер.

Репутация: 65
Всего: 372

Вызывается функция UStrCmp, которая и сравнивает эти строчки

MerCus, зачем нужен массив, когда можно свободно обойтись без него. Не устраивает мой пример, тем что он сортирует по первому столбцу? Но ведь не сложно его изменить так чтоб он сортировал по любому другому Массив, ИМХО, тут только лишний.

Репутация: нет
Всего: нет

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

спасибо всем за ответы, извините, что я туплю)) но мне это очень надо сделать, а у меня не получается

Репутация: 1
Всего: 27

сортируем String .Массив как буфер для ячеек по столбцам

Репутация: 65
Всего: 372

Код

unit Unit1;

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

const
ARRAY_SIZE = 5;

type
TArray = array of array of Integer;

Репутация: 53
Всего: 133

Короче, вы мне надоели. Простую задачку расжовываете уже вторую страницу. Вот код (единственное условие - в гриде должны быть ТОЛЬКО числовые значение, что, собственно, оговаривалось выше).

Сортируем StringGrid1 по 2 столбцу (в функцию передаем 1, т.к. в гриде отсчет начинается с 0).

Если хочешь, что бы что-то работало - используй написанное,
если хочешь что-то понять - пиши сам.

Репутация: 65
Всего: 372

Poseidon, первая строка у тебя вроде как не сортируется.

Кстати, чем мой код не устроил?

Репутация: 53
Всего: 133

Чесно? Много букафффф Если ради одной сортировки делать глобальную переменную, обьявлять новый тип, да еще саму сортировку разбивать на 3 процедуры, то даже страшно будеть посмотреть на весь проект. А еще не нравится мне, что твоя сортировка привязана к ARRAY_SIZE. Т.е. ее не применишь для двух разных гридов. Мало того, ее не применишь для не "квадратных" гридов. Да и боюсь даже заикаться про фиксированные строки, которые де-факто не должны участвовать в сортировке (они на то и фиксированные).

Если хочешь, что бы что-то работало - используй написанное,
если хочешь что-то понять - пиши сам.

Репутация: нет
Всего: нет

Репутация: 65
Всего: 372

MerCus, помечай тему как решенную.

Poseidon, не убедил)) у меня пример - пусть человек разбирается. У тебя готовое решение. Что лучше. Конечно же 1. В любом случае получай плюс за потраченное время и помощь ТС.

Репутация: 1
Всего: 27

А мой код чем плох? Он такой маленький а сортирует не хуже ваших.

Репутация: 53
Всего: 133

Добавлено через 14 минут и 35 секунд

  • Что если передаем таблицу отличную от размера 4х6 ?
  • Может я и придираюсь, но форматирование кода ужастное
  • Про фиксированные строки писать.
  • Привязка к конкретному гриду
Если хочешь, что бы что-то работало - используй написанное,
если хочешь что-то понять - пиши сам.

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

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

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

[ Время генерации скрипта: 0.1929 ] [ Использовано запросов: 21 ] [ GZIP включён ]

Я пишу программу на Delphi 10 / Seattle для управления Excel 2013. Мне нужно выполнить сортировку по столбцу. У столбца есть заголовки. Пока мой код компилируется, фактическая команда SORT выдает ошибку «Не удалось преобразовать вариант типа (Ошибка) в тип (логический)». Короче говоря, у меня неверный параметр, но я не могу определить КАКОЙ параметр. Я просмотрел синтаксис MS (URL-адрес указан ниже), но не нашел ничего неправильного. Вот рабочий образец, который показывает проблему. Я ДЕЙСТВИТЕЛЬНО создал свою собственную библиотеку типов, которая находится в предложении USES.

2 ответа

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

Вот возможный систематический подход, который может помочь найти рабочее решение:

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

Вот мой рабочий образец:

Наконец, я рад, что параметр Type не пожаловался на передачу EmptyParam , потому что я не понимаю, что это такое.


Старый ответ следует:

Я проверил ваши параметры с помощью маршрута IDispatch / Invoke, позднее связывание, как правило, у него более высокая вероятность приступить к работе, несмотря на потерю некоторой производительности и безопасности типов. Ни один из них не ошибается, я тестировал и другие ключи. Хотя параметры не являются неправильными, Excel выдает ошибку, если используется раннее связывание. Вот один рабочий пример:

Думаю, у вас было несоответствие требуемым параметрам. Ты должен попытаться

Удалите все непонятные параметры и замените их на Emptyparam, даже «true» или «false» иногда могут быть неясными, иногда мне приходилось использовать «wordbool (1)» или «msotrue» в коде Delphi вместо true

Читайте также: