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.