Успехов!
Вот код классца который помог легко решать мои задачи, а именно обеспечил простой доступ к содержимому ячеек первой страницы (необходимости читать все не было):
WorkWithExcel.H
#ifndef _WORKWITHEXCEL_H
#define _WORKWITHEXCEL_H
#pragma once
#include
using namespace std;
//вспомогательные интерфейсы, они видимо нужны
#import "C:\Program Files\Common Files\Microsoft Shared\OFFICE12\MSO.DLL"
#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB"
//импорт интерфейсов екселя с подменой названий методов
#import "C:\\Program Files\\Microsoft Office\\Office12\\excel.exe" \
rename( "DialogBox", "ExcelDialogBox" ) \
rename( "RGB", "ExcelRGB" ) \
rename( "CopyFile", "ExcelCopyFile" ) \
rename( "ReplaceText", "ExcelReplaceText" ) \
rename( "Rectangle", "ExcelRectangle" ) \
rename( "Arc", "ExcelArc" ) \
rename( "Picture", "ExcelPicture" ) \
rename( "Font", "ExcelFont" )
//--------------------------------------
class CWorkWithExcel
{
Excel::_ApplicationPtr m_pApplication;;
Excel::_WorkbookPtr m_pBook;
//текущая страница с которой читаются значения
Excel::_WorksheetPtr m_pActiveSheet;
public:
CWorkWithExcel(wstring file);
~CWorkWithExcel();
int m_Error;
double GetDoubleVal(int row, int col);
_variant_t GetVal(int row, int col);
};
//--------------------------------------
#endif
WorkWithExcel.cpp
#include "windows.h"
#include "atlbase.h"
#include "atlcom.h"
#include "WorkWithExcel.h"
//не используется в .h ибо идет перекрытие методов
using namespace Excel;
//--------------------------------------
CWorkWithExcel::CWorkWithExcel(wstring file)
{
m_pBook = 0;
m_pActiveSheet = 0;
m_Error = 0;
HRESULT hr = m_pApplication.CreateInstance( _T("Excel.Application"));
if (FAILED(hr))
return;
//тут try ибо в случае если файл не находится, то вываливается ексепшн, а не //возвращается код ошибки, впрочем слышал что можно импортнуть так, чтобы //возвращался код ошибки
try
{
m_pBook = m_pApplication->Workbooks->Open(_bstr_t(f
}
catch(...)
{
m_Error = 1;
return;
}
m_pActiveSheet = m_pBook->Sheets->Item[1];
}
//--------------------------------------
CWorkWithExcel::~CWorkWithExcel()
{
if (m_pBook)
// m_pApplication->Workbooks->Close();
m_pBook->Close();
}
//--------------------------------------
double CWorkWithExcel::GetDoubleVal(int row, int col)
{
double res = 0;
if (m_pActiveSheet && col <= m_pActiveSheet->Columns->Count
&& col >= 0 && row <= m_pActiveSheet->Rows->Count && row >=0)
{
Excel::RangePtr rp;
rp = m_pActiveSheet->Cells->Item[row][col];
res = rp->Value.dblVal;
}
return res;
}
//--------------------------------------
_variant_t CWorkWithExcel::GetVal(int row, int col)
{
_variant_t res = 0;
if (m_pActiveSheet && col <= m_pActiveSheet->Columns->Count
&& col >= 0 && row <= m_pActiveSheet->Rows->Count && row >=0)
{
Excel::RangePtr rp;
rp = m_pActiveSheet->Cells->Item[row][col];
res = rp->Value;
}
return res;
}
Над агентами поржал - первой была бабушка, бомжеватого, да простит меня, вида. Когда ее увидел захотелось пройти мимо, был еще студент, но пара была и приличных товарищей, видимо зависит от того кто это - частник или представитель агентства.
Некоторые шаблоны конечно же применяю, более успешно, но к слову те, которые и без книги знал, просто теперь я более четко знаю возможности ООП (шаблоны то на ООП построены), быстрее вижу выходы из ситуаций, причем красивые выходы а не абы как. У меня весьма удачно получилось применить к примеру шаблон модель - представление.
Итак. Первый же существенный минус студии - нельзя переключаться между хедером и его сиплюсплюсником (файлом), а также формой, соответствующей данному файлу (это Qt). Можно только сделать go to header. Это крайне существенный минус, который не дает нормально работать, ибо задалбливаешься мышкой щелкать, да еще надо найти файл (в закладках хотя бы).
И в той и в другой среде бывают косяки со списком методов класса (это когда в срр тыкнуть в какойто метод и наверху в комбобоксе появятся методы класса в который тыкнули), то есть они не видятся при какихто условиях. Разумеется это тоже не добавляет удобства ибо когда файл большой то задолбаешься искать. В таких случаях в студии не работает и go to definition.
Компиляция - здесь с громадным отрывом лидирует студия, ибо ребилд среднего приложения (12-15 файлов срр) занимает (точно не засекал) секунд 40, тогда как примерно такого же уровня приложение в билдере может по 300 секунд занимать (без всяких шуток, ребилд в билдере это вещь конечно приятная, ибо несколько минут можно о чемто помечтать, но все таки иногда на это уходит слишком много времени). Также в билдере есть другая беда - зачастую надо ребилдить весь проект, ибо не хватает перекомпиляции только файлов в которых были произведены изменения (с учетом зависимых хедеров), за полгода ни разу не столкнулся с такой бедой в студии.
В студии есть неплохая возможность располагать файлы в 2 таба, то бишь видеть сразу 2 файла на экране, в принципе помогает, я ей всегда пользуюсь, еще бы экран так в 22 инча...
В студии также можно проект сразу билдить в либу или длл (всего лишь указав в опциях тип выхода), в билдере для этого надо создавать отдельный проект специального типа.
Вобщем это были основные моменты которые для меня имеют большое значение. Про дизайнер говорить не хочется ибо там билдер на 10 корпусов впереди Qt-шного.
Конец.
Пришлось поюзать, вот мнение, возможно где-то не прав. Итак:
1. Нет мастер-детайл.
Конечно это продвинутая функция, но всетаки.
2. Нельзя получать доступ к столбцам по их имени, заодно и проверять существует ли столбец с таким именем. Это офигенный косяк, который не дает красиво и продуктивно работать. Для проверки наличия столбца нужна как дурак перебирать все. Даже сурцы просканировал, так и не нашел возможности.
3. Нельзя обратиться к ячейке (взять текст) если не был установлен item. Из-за этого если в ячейку на этапе загрузки не надо ничего писать, то либо все равно надо создавать item, либо потом в просмотре проверять а есть ли item, чтобы сделать item->text(). Неужто сделано для экономии памяти? Бред.
4. Когда создавал динамически колонки и поставил чтобы их ширина автоматически выравнивалась по содержимому, то последняя колонка выравнивалась по содержимому ячейки, а так как содержимое хедера было шире, то он обрезался, что было очень некрасиво. Как ни бился побороть не смог. Косяк.
Итог: хреновато, слабо. При том что цена Qt от 1780 до 6600 баксов (http://www.ii-system.com/partners/trollt
на работу. Мне тяжело было представить как можно тратить 3 часа в день только на добирание
до работы, учитывая что сама работа 8 часов. Но все таки приехал.
Итак, сколько я трачу времени и денег на дорогу. Сначала нужно добраться до метро - 15 минут
средним ходом, либо 4-5 мин на газели (20-25 руб в зависимости от номера), сначала правда её
нада дождаться и сесть (может быть забита). Дождаться в зависимости от случая 0 - 10 мин,
да до остановки 1 минута хода. Можно поехать на автобусе, его тоже надо дождаться и едет он
прилично медленней ибо останавливается на каждой остановке и если народу много то долго длится
процесс посадки ибо все заходят в одну дверь. Стоимость - 17 руб если купить билеты в киоске и
25 если у водителя. Таким образом видим что городские автобусы дороже и медленнее чем газели.
Затем подъезжаю к метро, спускаюсь, сажусь - это 2 - 4 минуты.
На метро еду с одной пересадкой, при пересадке нужно пройтись метров 250, впрочем переход не
самый страшный, бывают значительно хуже, я уж не говорю если надо 2 раза пересаживаться и
на переполненных станциях - там веселуха мама не горюй. До пересадки еду гдето 35-40 мин,
пересадка около 3 мин, далее до станции работы гдето 12 мин. Потом до проходной если пешем
то 11 мин (все время хожу пешем, ибо автобусы/газели надо ждать, платить, а выигрыша особого
не будет, а места там достаточно приятные и идти не скушно, особенно с музоном), далее 10 мин
от проходной до рабочего места.
Итого - 1,5 часа и денег от 35 (газель + оптом за метро дешевле чем 1 поездка (а одна поездка
нынче стоит 22 руб)) до 63 руб в одну сторону. Вот так вот. Могу сказать что расстояние гдето 25 км. На тачке кстати если б была хрен добере-
шься.
Короче задача у меня была следующая - нужно было чтоб при длительной загрузке данных
визуальный интерфейс не зависал, а отображал окно прогресса.
Это можно сделать и без потоков, если бы не было вызовов функций,
которые долго (0-5 сек в среднем, но в принципе до бесконечности)
не возвращали управление. Да и вообще наверно не хорошо чтобы в любой функции были вызовы репаинта интерфейса.
При этом хотелось бы чтобы логика вызова функций была неразвывной,
то есть такой как будто не используются потоки а идет вызов обычной функции.
Также поток должен был жить на протяжении жизни самого приложения, ибо в нем создавались объекты,
которые создавать каждый раз при запуске нового потока не есть гуд. Также не надо было
чтобы параллельно с работой потока еще чтото делалось,
поэтому нормально было чтобы программа не реагировала на воздействия во время загрузки.
Короче как я это сделал. Создал класс наследник QThread Mythread, а также класс ThreadObject
(наследник QObject чтоб подключить события) посредсвом которого будет происходить "незаметный" вызов методов объектов,
живущих в дочернем потоке. У Mythread в run написал что-то типа
run()
{
threadobject = new ThreadObject();
exec(); //включение цикла обработки сообщений потока, чтоб поток жил пока ему не пошлется сообщение выхода quit
delete threadobject;
}
Здесь надо бы упомянуть что чтобы вызвать код в другом потоке можно воспользоваться следующим способом применительно к Qt.
Если объект создан в потоке Х, то вызов его слотов будет происходить в потоке Х
(если не изменить последний параметр функции connect). Именно поэтому threadobject создается в run,
тк run - это другой поток, а скажем конструктор Mythread - это тот же поток в котором происходить создание объекта
этого класса (Mythread). В конструкторе ThreadObject происходит подключение событий,
посредством которых код вызывается в нужном потоке:
class ThreadObject
{
signals:
void StartProcess():при вызове этого сигнала сработает слот Process, который будет работать в потоке в котором создан объект ThreadObject
slots:
void Process();
InParameters m_InParameters;
OutParameters m_OutParameters;
ThreadObject()
{
connect(this, SIGNAL(StartProcess()), SLOT(Process()));
}
}
Слот Process имеет такой код:
void Process()
{
switch (state)
{
case GetValueA:
..... //какой-то код
SetEvent(ProcessComplete);//говорим что обработка завершилась
break;
case GetValueB:
OutParameters.doubleval = GetValueBMethod(InParameters.intval);//ч
SetEvent(ProcessComplete);//говорим что обработка завершилась
break;
}
}
int ThreadObject::GetValueBMethod(double val)
{
//тут может быть любой код, если он вызывается из метода Process то будет работать в том потоке в котором создан
//ThreadObject (ибо его в принципе можно вызвать и непосредственно, тогда он исполнится в том потоке, в котором был вызван)
return (int)val / 2;
}
Для того чтобы обеспечить передачу параметров внутри ThreadObject есть классы для входных и выходных параметров:
class InParameters
{
int intval;
double doubleval;
vector<int> vectorintval;
.... //описываются все необходимый входные данные
};
class OutParameters
{
int intval;
double doubleval;
....
};
Теперь посмотрим как выглядят функции для вызова извне, то есть те через которые собственно и будут получаться данные:
int ThreadObject::GetValueBMethod_(double val)
{
state = GetValueA;
InParameters.intval = val;
ResetEvent(ProcessComplete);//сбрасываем событие
while (WaitForSingleObject(ProcessComplete, 10) == WAIT_TIMEOUT)//ждем когда обработка завершится,
QCoreApplication::processEvents();/
return OutParameters.doubleval;
}
Замечание: Используются события винды, но можно заменить чем-нить другим.
Замечание: Код может быть слегка неправильным, ибо описываю основную идею, а не конкретику.
Итак, если бы нам нада была вызвать GetValueBMethod в этом же потоке то вызываем ThreadObject->GetValueBMethod(5);
если из другого, то ThreadObject->GetValueBMethod_(5);
При этом логика вызова будет одна и та же, можно абсолютно безболезненно заменить вызов метода
в другом потоке и ничего не придется менять.
В принципе ничего сложного, но для тех кто особо нерешителен и сомневается выбрать ли ему квт опишу процесс. Правда только под студию, в которую уже интегрирована qt. Итак качаем исходники с сайта, открываем файл проекта .pro в студии через пункт меню "Qt => open solution from ,pro", билдим. Появляются файлики qwt.lib и qwt.dll. Длл бросаем в кюте/бин или систем32, а в проекте где будете юзать квт (или в настройки среды, чтоб не указывать для каждого проекта) добавляете пути к инклудникам (.h) квт и .lib. И все
Следует помнить что если идет дебаг-версия проекта, то и дллку нужно юзать, собранную в дебаг-режиме, для релиза - релиз - версию, а то будет вылетать, а вы будете долго чесать репу почему.
Если хотите заюзать в наследнике класса qwtplot (а возможно и любого из библы квт) такую фигню как макрос Q_OBJECT, то неплохо бы в дефайны проекта добавить директивку QWT_DLL. Успехов!
Гость с Альдебарана
http://webfile.ru/2494551
Буй
http://webfile.ru/2494547
RBCsoft - пришел сказали что надо Си + мускул (проект loveplanet)(я как то думал что с++ (ну еще там чтото)), поэтому желание работать сразу пропало. Но стал отвечать на вопросы, они были не сложные, но я лоханулся примерно на таком вопросе
функция должна вернуть строку, как правильно?
char* func()
{
return "Ok";
}
char* func()
{
char str[] = "Ok";
return str;
}
и еще какието не варианты. Ну меня перекосячило и я сказал 2 (чото подумал что там динамическое выделение и поэтому все верно). Сказалось то, что в рабочей практике не работаю с char*, в билдере - AnsiString, std::string. Понятно что после такого отказали (еще пару вопросов небольших, вроде ответил пральна). Ну да и ладно.
диаграммы (чарты), причем qt до этого в глаза не видел, только слышал что есть
(в вакансиях часто требуется). Полазив по интернету пришел к выводу что практически единственное
и самое популярное средство (во всяком случае бесплатное, по платным ситуацию уже
не помню) - это библиотека qwt. Когда скачал, перехотелось её использовать,
ибо там было великое множество классов и методов и все только для того чтобы делать чарты.
В дизайнере разумеется ни хрена ничего не настраивается. При этом разумеется её надо было
собрать, с чем возникло тоже полно трудностей (в сумме наверно пол рабочего дня потратил на сборку).
В итоге волей-неволей пришлось изучать, смотря хелп и примеры, кои есть в достаточном количестве.
Причем фишка в том что в интернете про её использование не найти инфы, а на приличном форуме
по qt тоже не нашлось человека хорошо в ней разбирающегося (или все молчали). Нет, пару
человек сказали что использовали, но на вопросы (простейшие) никто не отвечал. Поэтому вкратце
скажу что я о ней думаю после 3 месяцев работы с qwt (не все разумеется 3 месяца, но постоянно приходилось
возиться).
Если вы до этого сидели на билдере с++ (как я), то конечно жопа полная. В билдере все
настраивается через дизайнер, ну чтото в коде (в основном то что тяжело через дизайнер),
тут же все вперед ручками. Для тех кто сидел на к'юте до этого это вобщем то не страшно,
ибо в к'юте в основном все ручками фигарится - это громаднейший минус. Причем к'юте платная
для использования в коммерции и к слову очень даже платная. Да и вообще, проработав уже 3 месяца
на к'юте в общей совокупности особых плюсов не заметил.
Но вернемся к qwt. Итак чтобы настроить к приеру шкалы нужно получить доступ к классу и через
него все настраивать, причем названия методов (а в кюте все делается через методы, а не
к примеру атрибуты (хотя бы какаято часть)) не больно то логичны, то есть с наскоку не
возьмешь. Чтобы сделать сетку нужно добавить специальный класс, чтобы сделать выделение
мышкой - тоже спец класс, а самое что убило - нет автонастройки лэйблов по осям, то есть
если вы хотите к примеру по оси х выводить дату, то придется унаследоваться от класса оси
и переопределить один метод, сделав преобразование из типа дабл к нужному нам типу по какой то
функции ибо по осям кюте понимает только дабл. При этом еще компонент еще и подглючивал -
рисовал метки за границей себя (для исправления этой фигни пришлось переписать пару методов (конечно
было изменено немного, но получилось очень некрасиво)).
Основная идея чартов - рисовать графики и соответственно нада загнать кудато данные.
Вот тут еще одна жопа - в qwt нет метода типа Линия->addvalue(x,y), там нада выделять динамически
массив даблов, его забивать и передавать в функцию, указывая длину - и такой бред в конце
2008 года! Пришлось написать свой собственный адаптер для перевода скажем вектора значений
в эту байду.
В целом сложилось впечатление что компонент тормознутый (нет, он аццки не тормозил, но не было
какойто легкости, как когда создаешь пустую форму на билдере с каким то еще компонентом и это
просто ЛЕТАЕТ), при этом комп - двухядерный кор на 2,4 ггц. Да и полное создание такого
компонента (с настроенными осями и тд) занимало не позволительное время - пришлось
создавать их не скопом, а по мере необходимости, ибо создание протормаживало интерфейс, что
крайне неприятно.
Кароче вывод такой - уж если связались с кюте, то видимо будете вынуждены использовать
и qwt (когда нужны будут диаграммы), а следовательно - готовьтесь!
Вначале хотел пойти в геймдев, так как люблю игры, но попосылав резюме таким товарищам как акелла, нивал и не
которым другим меня туда не пригласили. В итоге договорился только с одной небольшой фирмочкой
чуть-чуть за мкадом, но пройдя собеседование (или наоборот не пройдя) и заявив что хочу 50 тыр, мне отказали
(не сразу, сказали подумаем, но потом так и не ответили, пришлось самому связываться с ними).
В итоге пришел к выводу что в геймдев могут идти либо профи с некоторой потерей в зп но зато
заниматься любимым делом либо студенты - москвичи, которым меньше денег нада.
Соответственно пришлось обратить взор на обычную программерскую работу.
