jueves, 14 de enero de 2010

Registrar i desregistrar claus en un arxiu d'entrades de registre

La idea en aquesta nova aportació, és la de facilitar registrar i desenregistrar dades amb l'ajuda d'un arxiu d'entrades de registre. En el meu cas volia registrar una dll en un path de sistema. Per fer això, dins del path es volia afegir una variable de sistema. Per fer això i que el Windows ens tradueixi el path, el tipus de registre ha de ser REG_EXPAND_SZ. Llavors el registre es fa de la següent forma:

%ProgramFiles%\\MyFolder\\Mydll.dll

Guardat en una clau de tipus REG_EXPAND_SZ

El problema que vaig trobar, es que el valor del path en aquests registre ha d'estar en hexadecimal. Per trobar aquest valor, el sistema més senzill es obrir el regedit.exe i generar una clau d'aquest tipus. Un cop tenim la clau amb el path correcte l'exportem i l'afegim en els nostres fitxers .reg










Per comprovar que el path es correcte podem fer servir el UltraEdit. Es un editor molt complet, del que es pot baixar una versió d'avaluació de la pròpia pàgina. Amb ell podrem traduir el path escrit i comparar-lo amb el generat.

http://www.ultraedit.com/

Per trobar aquesta informació he consultat les següents pàgines:

http://msdn.microsoft.com/en-us/library/ms923642.aspx
http://en.wikipedia.org/wiki/Windows_Registry
http://www.pctools.com/forum/showthread.php?t=31388

Pel que fa la part de desenregistrar, solament hem d'afegir el símbol - dabant de la clau. Per exemple:

[-HKEY_CLASSES_ROOT\ObjecteCOM.coObjectCOM]

miércoles, 13 de enero de 2010

Com trobar el path d'un executable

Bones, l'aportació d'avui es molt curta, però no vol dir que no sigui útil. Perqué no sabem quan podem necessitar saber el path de l'executable on estem treballant. Per exemple, ens seria útil per mostrar imatges d'una carpeta que està dins de la carpeta on es troba el nostre executable. La solució es senzilla i parteix del paràmetre amb el que obtenim el path complet de l'executable. El codi és

exeFile := ParamStr(0);

Per obtenir solament el Path ho fem de la següent forma:

pathexeFile := ExtractFilePath(ParamStr(0));

Espero que això us sigui útil.

lunes, 4 de enero de 2010

MSBuild a Delphi 2007

M'he trobat amb el problema de voler moure una sèrie de fitxers dfm dins d'un path concret després de compilar. Com que no tots els fitxers es trobaven dins del mateix path, he optat per crear un Target personalitzat. L'utilització d'aquests targets esta comentada molt per sobre a llibre d'en Marco Cantú, Delph 2007 Handbook. En ell ens comentar un exemple d'afegir el resultat de la compilació en un fitxer .zip.

Tal i com es recomana, el que he fet es crear un nou fitxer .proj, en aquest fitxetr he definit el meu target. En el meu cas he fet servir un target estàndard de copia.

<?xml version="1.0" encoding="utf-8"?>
<
Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<FrontEndFiles Include="..\*.dfm;..\Articles\INTERFICIE\*.dfm;..\Clients\INTERFICIE\*.dfm;..\Colaboradors\*.dfm;..\Colaboradors\INTERFICIE\*.dfm;..\Compres\Interficie\*.dfm;..\ComunicacionsProgramesExterns\INTERFICIE\*.dfm;..\Facturacio\LIB\*.dfm;..\FormesDePagament\INTERFICIE\*.dfm;..\Frames\*.dfm;..\GestioEmpresa\*.dfm;..\HoresColaboradors\INTERFICIE\*.dfm;..\Instalacions\*.dfm;..\Instalacions\INTERFICIE\*.dfm;..\Moviments\INTERFICIE\*.dfm;..\Pressupostos\*.dfm;..\Proveidors\INTERFICIE\*.dfm" />
</ItemGroup>
<Target Name="Copy">
<Copy SourceFiles="@(FrontEndFiles)" DestinationFolder="$(OutputDir)" />
</Target>
<
/Project>



En aquest XML definim un nou target anomenat Copy i al tag FrontEndFiles incloem tots els fitxers i directoris que hem de tractar. Un cop fet això, hem d'afegir al dproj del projecte les següents dades:

<?xml version="1.0" encoding="utf-8"?>
<
Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" InitialTargets="build;Copy">
<Import Project="copy.proj" />



Això farà que s'executi el nostre target en finalitzar l'execució.







martes, 29 de diciembre de 2009

Error de ADO: 'No se puede encontrar la fila para su actualizacuón: algunos valores han cambiado desde la última vez que se leyó'

Aquest error es pot produir per diversos motius, per fer un update d'una fila mentre tens un query obert sobre la mateixa taula o fent modificacions amb triggers que modifiquin la mateixa taula, però el cas més extrany és el que ens pertoca. També es podrueix quan tens un trigger i dins d'aquest es realitza un SELECT, si aquesta instrucció no retorna cap valor MSSQL genera un error intern. No hi hauria cap problema si ADO no interpretés l'error intern com un error greu. De fet, surt el següent missatge d'error:





Per solucionar aquest tipus d'error, hem d'afegir al trigger el següent codi SET NOCOUNT ON a l'inici i SET NOCOUNT OFF al final. Llavors el codi quedaria de la següent forma:

CREATE TRIGGER [dbo].[XXXXX] ON [dbo].[Taula1]
FOR INSERT
AS
BEGIN
IF (SELECT COUNT(*) FROM INSERTED) > 0
BEGIN
SET NOCOUNT ON
INSERT INTO Taula2(
Camp1,
Camp2,
Camp3 )
SELECT
ins.Camp1,
ins.Camp3,
ins.Camp4
FROM INSERTED ins
WHERE (ins.Camp2 <> 'S')
AND (ISNULL(ins.Camp6, 0) > 0.001)
SET NOCOUNT OFF
END
END

martes, 18 de agosto de 2009

Control de MS Excel des de Delphi

Després de molt de temps, us faig una petita introducció al control de fulles excel des d'un programa realitzat en Delphi. El primer que hem de fer per controlar l'aplicació MSExcel es incorporar el servidor dins del nostre IDE.
Per a fer-ho, primer hem de importar els components de l'office. Anem a Component -> Import Components... i s'ens obre la següent pantalla







Un cop seleccionem aquesta opció, escollim per importar l'opció Import Type Library i escollim per importar Excel, Office i el motor office.














Un cop tenim seleccionades les dues llibreries de components, li hem de dir a al IDE com les volem utilitzar. Això ho fem a partir de la pantalla de component.















Amb aquesta pantalla creem el Wrappers i els afegim al nostre projecte. Ara solament quedarà fer-lose servir.

Utitlització
En una pantalla nova afegim un dels components nous que ens han aparegut en la paleta d'eines. El component ha de ser de la classe TExcelApplication. Un cop afegit el component, ens han d'apareixer els uses Excel_TLB i Office_TLB, que son els wrappers que ens permetran la funcionalitat.
Ara ja podem començar a treballar amb el control excel. Primer inicialitzarem el component:

XLApp1 := Excel_TLB.TExcelApplication.Create(self);


no hem d'oblidar-nos de desconectar el component:
XLApp1.Quit;
XLApp1.Disconnect;


Per obrir un excel i connectar-nos a ell, solament hem de fer connect i fer-lo visible.

XLApp1.Connect;
// Podem instal·lar nous components, programats per nosaltres.
obj := 'ExcelAddIn1';
XLApp1.COMAddIns.Item(obj).Connect := true;
XLApp1.OnWorkbookBeforeSave := XLAppWorkbookBeforeSave;
XLApp1.OnNewWorkbook := XLAppNewWorkbook;
XLApp1.Visible[GetUserDefaultLCID] := True;


Com es pot veure, també podem capturar una sèrie d'events. En el nostre cas, abans de guardar i quan l'usuari vol fer un nou full. D'aquesta forma podem controlar on es guarden els fulls i quin es el format al que volem que treballin.

Si volem obrir una nova fulla ho podrem fer com es mostra a l'exemple

procedure NouExcel;
var
objXLS: Excel_TLB.TExcelWorkbook;
objSheet: Excel_TLB.TExcelWorksheet;
begin
newWorkbook := XLApp1.Workbooks.Add('C:\Temp\Auxiliar.xlt', GetUserDefaultLCID);
objXLS := Excel_TLB.TExcelWorkbook.Create(nil);
objXLS.ConnectTo(newWorkbook);
objSheet := Excel_TLB.TExcelWorksheet.Create(nil);
objSheet.ConnectTo(objXLS.Worksheets['Xarxa'] as _Worksheet);

objSheet.Cells.Item[1, 2] := 'proves 1';
objSheet.Range[objSheet.Cells.Item[2, 2], objSheet.Cells.Item[2, 2]].NumberFormat := '@';
objSheet.Cells.Item[2, 2] := 'Valor defecte';
end;

De moment això es tot.

miércoles, 5 de noviembre de 2008

Freemem de BookMark

S'ha de tenir en compte que quan es treballa amb un TADOQuery i es vol fer servir un bookmark, si fem servir el mètode getBookMark s'ha d'alliberar la memòria. Això es degut a que getBookMark reserva un espai de memòria per guardar el punter.

function TDataSet.GetBookmark: TBookmark;
begin
if BookmarkAvailable then
begin
GetMem(Result, FBookmarkSize);
GetBookmarkData(ActiveBuffer, Result);
end else
Result := nil;
end;

Per tant s'hauria d'alliberar la memòria en aquests casos. Per a fer-ho tenim el mètode FreeBookMark(Bookmark: TBookmark). Que allibera el punter bookmark.

Codi d'exemple:

// Guardem on tenim situat el cursor actualment en el QDiari
QDiariBookmark := QDiari.GetBookmark;
try
..... Aquí podem afegir qualsevol codi
finally
QDiari.FreeBookmark(QDiariBookmark);
end;

lunes, 13 de octubre de 2008

jueves, 9 de octubre de 2008

Refresh d'un TADOQuery

En un TADOQuery no es pot fer un refresh, ja que està pensat per a treballar amb tres capes (datasnap). Fins ara el que feiem era obrir i tancar el query per refrescar-lo. He trobat i provat el següent codi i realment refresca el query sense la necessitat d'executar la consulta i enviar tots els missatges de nou. El codi que fa això es:

procedure Refresh(ds: TADOCustomDataSet)
var
book: TBookMark;
begin
book := ds.GetBookmark;
try
ds.Requery;
ds.GotoBookmark(book);
finally
ds.FreeBookmark(book);
end;
end;

viernes, 3 de octubre de 2008

Crear Documentació i Diagrames des del Model View de Delphi

Per crear la documentació del model UML i la generació de l'ajuda de programador a l'estil JavaDoc, hem de fer:


Ens apareixerà un diagrama amb les nostres classes:


Fent doble-click sobre aquesta, podem obrir el diagrama UML:


Un cop a sobre el model, podem fer botó dret per desplegar el menú contextual:



Generem la documentació a la ruta indicada:



Un cop generada tota la documentació, podem accedir a la informació mitjançant l'index.html que apareixerà dins la ruta de generació de documentació.