Сжать программно dbf
О чем идет речь - о выполнении операции очистки таблицы от удаленных записей? Для этого используется DbiPackTable.
Если же надо просто упаковать - то, например для рара можно так:
HANDLE newstdout,read_stdout;
SECURITY_ATTRIBUTES sa;
SECURITY_DESCRIPTOR sd;
STARTUPINFO si;
PROCESS_INFORMATION pi;
InitializeSecurityDescriptor(&sd,SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&sd, true, NULL, false);
sa.lpSecurityDescriptor = &sd;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = true;
if (!CreatePipe(&read_stdout,&newstdout,&sa,0))
ShowMessage("Error Create PIPE");
TDateTime dt;
GetStartupInfo(&si);
si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
si.hStdOutput = newstdout;
si.hStdError = newstdout; //подменяем дескрипторы для
dt= Now();
String str = dt.FormatString(("DDMMYYYYHHMMSS"));
String tt = "rar32.exe m -y -ep1 "+str + ".ras" + " *.dbf";
si.cb = sizeof(si);
si.dwFlags =STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
ZeroMemory( &pi, sizeof(pi) );
CreateProcess(NULL, tt.c_str() , NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si,&pi );
WaitForSingleObject(pi.hThread,10000);
упакует все файлы с расширением дбф в текущей директории в файл с расширением .ras и текущим временем в качестве имени при условии конечно что rar32.exe находится в путях поиска. Если нет - тогда надо указать полный путь.
Я сделал примерно так:
Table1->Close();
Table1->Exclusive=true;
Table1->Open();
DbiPackTable(Table1->DBHandle,Table1->Handle, NULL,NULL,true);
Table1->Close();
Table1->Exclusive = false;
Table1->Open();
но ничего не получилось. Ошибку не выдал, но и база не сжалась.
Можно поподробнее пожалуйста. Я использую компонент ADOQuery.
Я сделал примерно так:
Table1->Close();
Table1->Exclusive=true;
Table1->Open();
DbiPackTable(Table1->DBHandle,Table1->Handle, NULL,NULL,true);
Table1->Close();
Table1->Exclusive = false;
Table1->Open();
но ничего не получилось. Ошибку не выдал, но и база не сжалась.
Можно поподробнее пожалуйста. Я использую компонент ADOQuery.
Ничего не получилось - это как?
Приведите ваш код. С тем компонентом который вы используете.
Ничего не получилось - это как?
Приведите ваш код. С тем компонентом который вы используете.
я нашел вышепреведенный код в инете, попробовал его воспроизвести как был с table(но мне надо с ADOQuery). При нажатии на кнопку прога сработала, но удаленные записи так и остались в базе.
я нашел вышепреведенный код в инете, попробовал его воспроизвести как был с table(но мне надо с ADOQuery). При нажатии на кнопку прога сработала, но удаленные записи так и остались в базе.
Вы не задавались вопросом - причем здесь ADOQuery к TDBDataSet свойства которого собственно и используются в приведеном вами коде? Или операция копи-пасте уже освоена, но клавиша Ф1 попрежнему недоступна?
Я думаю что если бы вы не передирали бездумно код из тырнета то он бы у вас выглядел бы вот так:
...
result = DbiPackTable(ADOQuery1->DBHandle,ADOQuery1->Handle, NULL,NULL,true);
if(result != DBIERR_NONE){
switch(result){
case DBIERR_INVALIDHNDL:
//Вывод сообщения о ошибке подключения к БД
break;
...
/*остальные проверки, хотябы на то что таблица которую вы собрались сжимать - существует*/
default:
//Неизвестная ошибка
}
return ERROR;
}
return OK;
выходом из этой ситуации может быть использование функций BDE API не только для сжатия таблицы но и для открытия ее, или использование компонентов TBDE.... вместо TADO...
Вы не задавались вопросом - причем здесь ADOQuery к TDBDataSet свойства которого собственно и используются в приведеном вами коде? .
Я имел в виду: Попробовал воспроизвести код как был, с Table.
Прописав ошибки:
result = DbiPackTable(Form1->Table1->DBHandle,Form1->Table1->Handle, NULL,NULL,true);
if(result != DBIERR_NONE){
switch(result){
case DBIERR_INVALIDHNDL: ShowMessage("The specified database handle or cursor handle is invalid or NULL");
break;
case DBIERR_INVALIDPARAM: ShowMessage("The specified table name or the pointer to the table name is NULL");
break;
case DBIERR_NOSUCHTABLE: ShowMessage("Table name does not exist");
break;
case DBIERR_UNKNOWNTBLTYPE: ShowMessage("Table type is unknown.");
break;
case DBIERR_NEEDEXCLACCESS: ShowMessage("The table is not open in exclusive mode.");
break;
default:
ShowMessage("неизвестная ошибка");
}
return false;
}
return true;
получил - "неизвестная ошибка". Подскажи, пожалуйста, в чем еще может быть ошибка.
Я имел в виду: Попробовал воспроизвести код как был, с Table.
Прописав ошибки:
result = DbiPackTable(Form1->Table1->DBHandle,Form1->Table1->Handle, NULL,NULL,true);
получил - "неизвестная ошибка". Подскажи, пожалуйста, в чем еще может быть ошибка.
Таблица открыта в эксклюзивном режиме (по коду это не видно, у меня в коде просто опущено)?
Точку останова перед вызовом функции и смотри что передается и что возвращается. Сжатие базы не происходит точно?
Точку останова перед вызовом функции и смотри что передается и что возвращается. Сжатие базы не происходит точно?
Таблица открыта в эксклюзивном режиме. А что должно передаваться?
Ни одна из известных ошибок не определяется, а возвращается false.
Буду вам признателен, если напишите полный рабочий пример от начала
и до конца.(может с другой функцией).
Ни одна из известных ошибок не определяется, а возвращается false.
Буду вам признателен, если напишите полный рабочий пример от начала
и до конца.(может с другой функцией).
В функцию должен быть передан указатель на открытую BDE-базу (т.е. она должна присуствовать в списке баз бде-администратора, или созданой "на лету") и указатель на открытую в эксклюзивном режиме BDE-таблицу. Судя по тому что вы пишите, у вас как минимум одно условие не соблюдается - вы используете АДО-компоненты. С ними функция корректно работать не сможет. Возможно именно с этим и связана ошибка.
Код напишу вечером, если будет время.
Для того что бы использовать апи бде вам необходимо:
1. Инициализировать подсистему.
2. Открыть базу данных.
3. Если нужно - получить(открыть) дескриптор таблицы (нам это не нужно).
4. Выполнить операцию (в данном случае упаковать таблицу)
5. Закрыть всю эту фигню. :)
DbiInit(NULL);
phDBIDb phDb;
phDb = (phDBIDb)malloc(sizeof(hDBIDb));
//открываем базу testAPI и получаем дескриптор на нее
resdb = DbiOpenDatabase("testAPI", NULL, dbiREADWRITE, dbiOPENSHARED,NULL, 0, NULL, NULL, *phDb);
//пакуем таблицу test.db
resdb= DbiPackTable(*phDb, NULL, "test.db", NULL, TRUE);
DbiCloseDatabase (phDb);
DbiExit ();
обработку ошибок я оставляю естественно на ваше усмотрение.
Код проверен и работает при соблюдении условий указанных выше.