unit ScProjectManager; interface uses DataBase, Classes, ScFileArchiver, ConstTypeUnit, Windows, BillsProjectFrame, ConstVarUnit, ScUpdateDataBase, Forms, Variants, HisRestorePointDM, ScExprsDM, ProjectPropertyDM, ImportExcel, ADODB, DetailItemsDM, ExportExcel, ScReportDM, RecycleBinDM; type TProject = class private FID : Integer; FFlag : Integer; FParentID : Integer; FNavigation : Integer; FFilePath : string; FProjectName : string; FChanged : Boolean; FDMExprs : TDMExprs; FStdBillsCtrl : TObject; FBillsData : TDMDataBase; FProjPropertyDM : TProjPropertyDM; FRecycleBinData : TRecycleBinData; FDMHisPoint : TDMHisRestorePoint; FProjectView : TBillsProjectView; FDetailItemsDM : TDMDetailItems; FArchiver : TScProjectFileArchiver; // chenshilong, 2011-01-13 11:23:05 FReport : TReportData; FOpenForReport : Boolean; // 显示报表前要修改SerialNo,用完后会提示项目保存,加个条件不让提示 FChangedByReport: Boolean; // 强制不保存。如新建项目后关闭,预览报表后关闭。 FForceUndoSave: Boolean; procedure SetStdBillsCtrl(const Value: TObject); function NewFile(const aFileName, TempleteFile: string; var aNewName: string): Boolean; { save project } procedure InnerSave; procedure Save; overload; procedure InitNewProject; function GetProjectType: Integer; procedure SetProjectName(const Value: string); function GetConnection: TADOConnection; procedure SetBidLotList(const Value: TStrings); procedure SetFlag(const Value: Integer); public constructor Create(const FileName, aShortName: string; ProjectType, aID: Integer); destructor Destroy; override; procedure Save(const aCreatePoint: Boolean; aFixed: Boolean = False); overload; procedure SaveAs(const FileName: string); // Added by GiLi 2012-3-16 17:17:36 // 重新设置文件的别名 procedure ResetFileAlias(const sNewAlias: string); function NeedSaveDatabase: Boolean; { gather project } procedure CheckBeforeGather; function GetGatherID: Integer; function GatherProject(ANewProject: TProject): Boolean; { import excel file } procedure ImportExcelFile(const aFileName: string); procedure ImportQtyItems(const aFileName: string); procedure ExportExcel(aProjMgr: TObject; const aFileName: string; aStrings: TStrings; aFlag: Integer); procedure ExportFlatExcel(const AFileName: string); { 1. File Manager } property ID: Integer read FID; // Flag=1 : 建设项目 Flag=2 : 标段 Flag=3 : 项目清单 property Flag: Integer read FFlag write SetFlag; property ParentID: Integer read FParentID write FParentID; property BidLotList: TStrings write SetBidLotList; { 2. Active Objects } property BillsData: TDMDataBase read FBillsData; property ProjPropertyDM: TProjPropertyDM read FProjPropertyDM; property DMHisPoint: TDMHisRestorePoint read FDMHisPoint; property ProjectView: TBillsProjectView read FProjectView; property StdBillsCtrl: TObject read FStdBillsCtrl write SetStdBillsCtrl; property DetailItemsDM: TDMDetailItems read FDetailItemsDM; property RecycleBinData: TRecycleBinData read FRecycleBinData; { 3. Connection } property Connection: TADOConnection read GetConnection; property Archiver: TScProjectFileArchiver read FArchiver; { 4. project Base Property } property Changed: Boolean read FChanged write FChanged; property FilePath: string read FFilePath write FFilePath; property ProjectName: string read FProjectName write SetProjectName; property ProjectType: Integer read GetProjectType; property Navigation: Integer read FNavigation write FNavigation; property Report: TReportData read FReport write FReport; property OpenForReport: Boolean read FOpenForReport write FOpenForReport; property ChangedByReport: Boolean read FChangedByReport write FChangedByReport; property ForceUndoSave: Boolean read FForceUndoSave write FForceUndoSave; end; TProjectManager = class private FProjectList: TList; FProjType: TScProjType; FActiveIndex: Integer; FActiveProject: TProject; function FindProject(const AIdx: Integer): TProject; function GetProjectCount: Integer; function GetProject(Idx: Integer): TProject; procedure SaveAllProjects(const aCreatePoint: Boolean); procedure SaveCurProject(const aCreatePoint: Boolean); public constructor Create; destructor Destroy; override; {open or create new project} function CreateNewProject(const FileName, aShortName: string; AStdBillsCtrl: TObject; AProjectType, aID: Integer): TProject; {find project by index} function LocateProject(const AIdx: Integer): Boolean; {remove project} function RemoveProject(Project: TProject = nil; AProject: TProject = nil; IsExist: Boolean = True): Integer; function RemoveProjectForClose(var CanColse: Boolean; Project: TProject = nil; AProject: TProject = nil; IsExist: Boolean = True): Integer; {save projects} procedure SaveProjects(const aSaveAll, aCreatePoint: Boolean); {find project by name} function CheckProjectExists(const AFileName: string): Integer; procedure ResetAllOpenProjectView; property Projects[Idx: Integer]: TProject read GetProject; property ProjectCount: Integer read GetProjectCount; property ActiveProject: TProject read FActiveProject; property ActiveIndex: Integer read FActiveIndex; property ProjectList: TList read FProjectList write FProjectList; // chenshilong, 2011-01-12 16:09:00 // 为预览报表打开创建汇总项目 function OpenProjectForReport(AFileName: string): TProject; // 关闭为预览报表而打开创建的汇总项目 procedure CloseProjectsForReport; procedure SetReportsFirstGetData; function GetProjectByID(AID: Integer): TProject; end; implementation uses SysUtils, ConstMethodUnit, ScKindsOfTrees, ZjIDTree, ExportDecorateUnit, SMCells, SMXLS, MainForm, ProjectManagerDM, ScProgressFrm; { TProjectManager } function TProjectManager.CheckProjectExists( const AFileName: string): Integer; var I: Integer; project: TProject; begin Result := -1; for I := 0 to FProjectList.Count - 1 do begin project := TProject(FProjectList.List^[I]); if SameText(AFileName, project.FilePath) then begin Result := I; Break; end; end; end; constructor TProjectManager.Create; begin FProjectList := TList.Create; {$IFDEF _ScBills} FProjType := ptBills; {$ELSE} FProjType := ptBudget; {$ENDIF} end; function TProjectManager.CreateNewProject(const FileName, aShortName: string; AStdBillsCtrl: TObject; AProjectType, aID: Integer): TProject; var strName: string; begin case FProjType of ptBills: strName := BillsTemplateFile; ptBudget: strName := BudgetTemplateFile; end; Result := TProject.Create(FileName, aShortName, AProjectType, aID); Result.StdBillsCtrl := AStdBillsCtrl; FActiveIndex := FProjectList.Add(Result); FActiveProject := Result; end; procedure TProjectManager.CloseProjectsForReport; var I: Integer; vProject: TProject; begin for I := FProjectList.Count - 1 downto 0 do begin vProject := TProject(FProjectList[I]); if vProject.OpenForReport then begin vProject.Free; FProjectList.Delete(I); end; end; end; destructor TProjectManager.Destroy; var I: Integer; project: TProject; begin for I := FProjectList.Count - 1 downto 0 do begin project := TProject(FProjectList[I]); if MainFrm.IsSave then begin if project.NeedSaveDatabase then begin if MessageBox(0, PChar(Format('项目[%s]已被修改, 是否保存项目?', [project.ProjectName])), PChar('询问'), MB_YESNO or MB_ICONQUESTION or MB_TOPMOST) = IDYES then project.Save; end; end; project.Free; end; FProjectList.Free; inherited; end; function TProjectManager.FindProject(const AIdx: Integer): TProject; begin if (AIdx > -1) and (AIdx < FProjectList.Count) then Result := TProject(FProjectList[AIdx]) else Result := nil; end; function TProjectManager.GetProject(Idx: Integer): TProject; begin if (Idx >= 0) and (Idx < FProjectList.Count) then Result := TProject(FProjectList.List^[Idx]) else Result := nil; end; function TProjectManager.GetProjectCount: Integer; begin Result := FProjectList.Count; end; function TProjectManager.LocateProject(const AIdx: Integer): Boolean; var Project: TProject; begin Project := FindProject(AIdx); if Assigned(Project) then begin FActiveProject := Project; FActiveIndex := AIdx; Result := True; end else begin Result := False; FActiveIndex := -1; end; end; function TProjectManager.OpenProjectForReport(AFileName: string): TProject; var vArchiver: TScProjectFileArchiver; iIdx, ProID: Integer; sName, ProName: string; aqExec: TADOQuery; begin if not FileExists(AFileName) then begin Result := nil; Exit; end; vArchiver := nil; iIdx := CheckProjectExists(AFileName); if iIdx = -1 then begin CreateProgressForm(100); AddProgressForm(20, '汇总项目尚末打开,正在从后台打开……'); try vArchiver := TScProjectFileArchiver.Create; vArchiver.FileName := AFileName; vArchiver.OpenFile; sName := ExtractFileName(AFileName); sName := Copy(sName, 1, Length(sName) - 4); with MainFrm.ProjectFileManager.ProjectMgrDM do begin aqExec := TADOQuery.Create(nil); try aqExec.Connection := aqGatherBid.Connection; aqExec.SQL.Add(Format('Select * from ProjectManager where Flag = 3 and UnKnowName = ''%s''', [sName])); aqExec.Open; if aqExec.RecordCount > 0 then begin ProID := aqExec.FieldByName('ID').AsInteger; ProName := aqExec.FieldByName('ProjectName').AsString; end else begin Result := nil; Exit; end; finally aqExec.Free; end; end; Result := TProject.Create(AFileName, ProName, -1, ProID); Result.OpenForReport := True; FProjectList.Add(Result); Result.BillsData.Connection := vArchiver.Connection; UpdateDB(vArchiver); vArchiver.Save; Result.BillsData.Active := True; Result.BillsData.ConnectionBillsTree; Result.Report.RefreshData; finally CloseProgressForm; end; end else begin Result := Projects[iIdx]; Result.Report.RefreshData; end; if Assigned(vArchiver) then vArchiver.Free; end; function TProjectManager.RemoveProject(Project: TProject; AProject: TProject; IsExist: Boolean): Integer; var curProject: TProject; begin curProject := Project; if Assigned(Project) then Result := FProjectList.Remove(Project) else begin curProject := FActiveProject; Result := FProjectList.Remove(FActiveProject); end; if Assigned(curProject) then begin if curProject.NeedSaveDatabase then begin if IsExist then begin if MessageBox(0, PChar(Format('项目 [%s] 已被修改,是否保存?', [curProject.ProjectName])), PChar('询问'), MB_YESNO or MB_TOPMOST or MB_ICONQUESTION) = IDYES then curProject.Save(True); end else curProject.Save(True); end; curProject.Free; end; if Assigned(AProject) then FActiveProject := AProject else begin if FProjectList.Count = 0 then FActiveProject := nil else if Result < FProjectList.Count then FActiveProject := TProject(FProjectList[Result]) else FActiveProject := TProject(FProjectList[Result - 1]); end; FActiveIndex := FProjectList.IndexOf(FActiveProject); end; procedure TProjectManager.SaveAllProjects(const aCreatePoint: Boolean); var I: Integer; project: TProject; begin for I := 0 to FProjectList.Count - 1 do begin project := TProject(FProjectList.List^[I]); if project.NeedSaveDatabase then project.Save(aCreatePoint); end; end; procedure TProjectManager.SaveCurProject(const aCreatePoint: Boolean); begin if Assigned(FActiveProject) and FActiveProject.NeedSaveDatabase then FActiveProject.Save(aCreatePoint); end; procedure TProjectManager.SaveProjects(const aSaveAll, aCreatePoint: Boolean); begin if aSaveAll then SaveAllProjects(aCreatePoint) else SaveCurProject(aCreatePoint); end; procedure TProjectManager.SetReportsFirstGetData; var I: Integer; vReport: TReportData; begin for I := 0 to FProjectList.Count - 1 do begin vReport := TProject(FProjectList[I]).Report; vReport.FirstGetData := True; end; end; function TProjectManager.GetProjectByID(AID: Integer): TProject; var i: Integer; begin Result := nil; for i := 0 to FProjectList.Count - 1 do begin if TProject(FProjectList[i]).ID = AID then begin Result := TProject(FProjectList[i]); Break; end; end; end; function TProjectManager.RemoveProjectForClose(var CanColse: Boolean; Project: TProject = nil; AProject: TProject = nil; IsExist: Boolean = True): Integer; var curProject: TProject; MQResult: Integer; begin curProject := Project; if not Assigned(Project) then begin curProject := FActiveProject; end; if Assigned(curProject) then begin if curProject.NeedSaveDatabase then begin if IsExist then begin MQResult := MessageBox(0, PChar(Format('项目 [%s] 已被修改,是否保存?', [curProject.ProjectName])), PChar('询问'), MB_YESNOCANCEL); case MQResult of ID_YES: begin CanColse := True; curProject.Save(True); end; ID_NO: begin CanColse := True; end; IDCANCEL: begin CanColse := False; Exit; end; end; end else curProject.Save(True); end else CanColse := True; if CanColse then Result := FProjectList.Remove(curProject); curProject.Free; end; if Assigned(AProject) then FActiveProject := AProject else begin if FProjectList.Count = 0 then FActiveProject := nil else if Result < FProjectList.Count then FActiveProject := TProject(FProjectList[Result]) else FActiveProject := TProject(FProjectList[Result - 1]); end; FActiveIndex := FProjectList.IndexOf(FActiveProject); end; procedure TProjectManager.ResetAllOpenProjectView; var i: Integer; begin for i := 0 to FProjectList.Count - 1 do TProject(FProjectList.Items[i]).ProjectView.LoadBillsViewOption; end; { TProject } constructor TProject.Create(const FileName, aShortName: string; ProjectType, aID: Integer); var strNewPath: string; begin FOpenForReport := False; FChangedByReport := False; FForceUndoSave := False; strNewPath := FileName; {project file path} FFilePath := strNewPath; FID := aID; FArchiver := TScProjectFileArchiver.Create; FArchiver.FileName := strNewPath; // Added by GiLi 2012-3-16 16:09:41 FArchiver.Alias := '三级清单'; FArchiver.OpenFile; if FArchiver.IsStdFile then begin FArchiver.IsStdFile := False; FChanged := True; end; PScFileHead(@FArchiver.FileInfo).ProductName := ConstProductName; FChanged := True; FBillsData := TDMDataBase.Create(Self); FBillsData.Connection := FArchiver.Connection; UpdateDB(FArchiver); {先打开数据,然后连接界面,效率快些} FBillsData.Active := True; FDMExprs := TDMExprs.Create(nil); FDMExprs.Connection := FArchiver.Connection; FBillsData.DMExprs := FDMExprs; if ProjectType <> -1 then begin FBillsData.DeleteAllBills(False); InitNewProject; end; FBillsData.ConnectionBillsTree; FDMHisPoint := TDMHisRestorePoint.Create(nil); FDMHisPoint.Connection := FArchiver.Connection; FDMHisPoint.ProjectPath := FFilePath; FDMHisPoint.ProjectName := aShortName; {修改项目属性} FProjPropertyDM := TProjPropertyDM.Create(nil); FProjPropertyDM.Connection := FArchiver.Connection; if ProjectType <> -1 then begin FProjPropertyDM.EditProjProperty(ProjectType); FProjPropertyDM.Save; // Added by GiLi 2012-3-16 16:09:41 FArchiver.Alias := aShortName; FArchiver.Save; end; // Added by GiLi 2012-3-16 19:01:19 FArchiver.Alias := aShortName; FDetailItemsDM := TDMDetailItems.Create(Self); FRecycleBinData := TRecycleBinData.Create(nil); FRecycleBinData.Connection := FArchiver.Connection; FReport := TReportData.Create(nil); FReport.Project := Self; FProjectView := TBillsProjectView.Create(Self); // FProjectView.jpDetails.Height := 240; ProjectName := aShortName; FBillsData.EnabledUITreeEvt := FProjectView.ControlBillsTreeRT; FBillsData.EnabledUIDrawQtyEvt := FProjectView.ControlDrawQtyRT; FBillsData.DesignCodeEvt := FProjectView.ControlDesignCode; end; destructor TProject.Destroy; begin FDetailItemsDM.Free; FRecycleBinData.Free; FreeAndNil(FArchiver); { Note:first release UI, and then release database } FreeAndNil(FProjectView); FreeAndNil(FBillsData); FreeAndNil(FDMHisPoint); FreeAndNil(FDMExprs); FreeAndNil(FProjPropertyDM); FreeAndNil(FReport); inherited; end; function TProject.GatherProject(ANewProject: TProject): Boolean; var CacheGatherTree: TCacheGatherTree; begin Result := False; CacheGatherTree := TCacheGatherTree.Create; IncProgressUI(15); try if CacheGatherTree.TraverseDBIntoSelf(Self) then begin IncProgressUI(35); CacheGatherTree.TraverseOwnerIntoDB(ANewProject); IncProgressUI(45); Result := True; end; finally CacheGatherTree.Free; end; end; procedure TProject.ImportExcelFile(const aFileName: string); var exImportor: TExcelImportor; begin exImportor := TExcelImportor.Create(FBillsData, aFileName); // Added by GiLi 2012-4-18 15:02:01 // 使用新的进度条 CreateProgressForm(100, '正在导入Excel清单文件>>>'); try exImportor.ImportExcel; FDetailItemsDM.PQEmptyDetail; finally exImportor.Free; CloseFloatProgress; IncProgressUI(100); end; end; procedure TProject.InnerSave; begin FBillsData.Save; FDMExprs.Save; FRecycleBinData.Save; // FDMHisPoint.Save; end; function TProject.NeedSaveDatabase: Boolean; begin Result := (FBillsData.ShouldSave or FChanged) and (not FForceUndoSave); end; procedure TProject.Save; begin IncProgressUI(5); InnerSave; IncProgressUI(60); FArchiver.Save; IncProgressUI(35); FChanged := False; end; function TProject.NewFile(const aFileName, TempleteFile: string; var aNewName: string): Boolean; var strTemPath: string; begin strTemPath := Format('%s\Data\%s', [ExtractFileDir(ParamStr(0)), TempleteFile]); aNewName := Format('%s\我的清单\%s.smb', [ExtractFileDir(ParamStr(0)), aFileName]); Result := CopyFile(PChar(strTemPath), PChar(aNewName), True); end; procedure TProject.Save(const aCreatePoint: Boolean; aFixed: Boolean); begin Save; if aCreatePoint then FDMHisPoint.SavePoint(aFixed); FArchiver.Save; end; procedure TProject.SaveAs(const FileName: string); begin IncProgressUI(5); InnerSave; IncProgressUI(60); FArchiver.SaveTo(FileName); IncProgressUI(35); end; procedure TProject.SetStdBillsCtrl(const Value: TObject); begin FStdBillsCtrl := Value; FBillsData.StdBillsCtrl := FStdBillsCtrl; FProjectView.StdBillsCtrl := FStdBillsCtrl; end; function TProject.GetProjectType: Integer; begin Result := FProjPropertyDM.GetProjectType; end; procedure TProject.SetProjectName(const Value: string); begin FProjectName := Value; FDMHisPoint.ProjectName := FProjectName; end; procedure TProject.ImportQtyItems(const aFileName: string); var exImportor: TExcelImportor; begin exImportor := TExcelImportor.Create(FBillsData, aFileName); try exImportor.ImportQtyItems; finally exImportor.Free; end; end; procedure TProject.ExportExcel(aProjMgr: TObject; const aFileName: string; aStrings: TStrings; aFlag: Integer); var eeExportor: TExcelExportor; begin eeExportor := TExcelExportor.Create(FBillsData, aProjMgr); try eeExportor.ExportToExcel(aFileName, aStrings, aFlag); finally eeExportor.Free; end; end; function TProject.GetConnection: TADOConnection; begin Result := FArchiver.Connection; end; function TProject.GetGatherID: Integer; begin if FFlag = 3 then Result := FParentID else Result := FID; end; procedure TProject.CheckBeforeGather; begin if (FID = -1) or (FFlag = 1) then raise Exception.Create('建设项目或预览项目不能汇总.'); end; procedure TProject.SetBidLotList(const Value: TStrings); begin FProjectView.BidLotList := Value; end; procedure TProject.SetFlag(const Value: Integer); begin FFlag := Value; FProjectView.ControlOwnerBid(FFlag); end; procedure TProject.InitNewProject; var Decorator: TDecorator; begin Decorator := TCreateDecorator.Create(FBillsData, {$I ProjectBills.inc}); try Decorator.Decorate; finally Decorator.Free; end; end; // Added by GiLi 2012-3-16 17:18:14 // 重新设置文件的别名 procedure TProject.ResetFileAlias(const sNewAlias: string); begin if Assigned(FArchiver) then begin FArchiver.Alias := sNewAlias; FArchiver.Save; end else raise Exception.Create('文件重命名出错!'); end; procedure TProject.ExportFlatExcel(const AFileName: string); var Exportor: TFlatGclExcelExportor; begin Exportor := TFlatGclExcelExportor.Create(FBillsData); try Exportor.ExportFile(aFileName); finally Exportor.Free; end; end; end.