Created
June 4, 2024 12:49
-
-
Save boumer7/4c23e555f02ec8f444add19dc911c18d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// Инициализация вновь созданного объекта. | |
/// Вызывается на клиенте (или на сервере в клиентском скрипте) | |
/// сразу после установки значений по умолчанию в атрибутах | |
/// </summary> | |
/// <param name="obj">Объект, который инициализируем</param> | |
/// <param name="initialValues">Список значений для инициализации атрибутов объекта</param> | |
/// <remarks>Метод вызывается в порядке от шаблонов-родителей к детям-модификаторам.</remarks> | |
public override void OnInitialize(InfoObject obj, Dictionary<string, object> initialValues) | |
{ | |
UpdateItemList(obj); | |
obj["InitFinished"] = true; | |
} | |
/// <summary> | |
/// Вызывается внутри скриптового (клиентского и серверного) кода перед передачей | |
/// серверу команды на изменение объектов. | |
/// Обработчики вызываются в порядке от родительских шаблонов к дочерним и модификаторам. | |
/// </summary> | |
/// <param name="obj">Объект, изменения в котором собираемся отправлять на сервер</param> | |
/// <remarks>Физически может вызываться как на клиенте, так и на сервере, если сохранение иницировано | |
/// например серверным методом, или другим скриптовым кодом. | |
/// Исключения, вышедшие их этого метода, предотвращают сохранение объекта. | |
/// Пользователю показывается сообщение. | |
/// Следует иметь в виду, что этот метод может вызываться несколько раз для одних и тех же входных данных. | |
/// Такое бывает в случае нескольких неуспешных попыток пользователя сохранить объект. В этом случае, | |
/// если метод изменяет что-ли в объектах, на которых у исходного набора есть ссылки, то повторные вызовы | |
/// метода могут привести к использованию уже измененных связанных скриптовых оболочек. | |
/// Возможно для таких объектов понадобится вызывать CancelChanges() либо EnsureObjectInSaveSet(), чтобы | |
/// эти измененные объекты попали в новый контекст очередной попытки сохранения. | |
/// Метод вызывается в порядке от шаблонов-родителей к детям-модификаторам. | |
/// [ReplaceMaster] атрибут позволяет из скрипта модификатора отключить обработчик мастер-шаблона</remarks> | |
public override void OnBeforeSendChangesToServer(InfoObject obj) | |
{ | |
var fileName = obj.GetString("Name").Replace(':', '_').Replace('/', '_'); | |
var replaceDots = Service.GetCommonRegistryValue<int>(@"KB20Root\CommonSettings\KB20_Unloading_str\ReplaceDots\Value", 1) == 1; | |
if (replaceDots) | |
fileName = fileName.Replace('.', '_'); | |
// Нужно ли выгружать из PLM или Создавать в PLM Тех.Док. | |
if (obj.GetBoolean("UnloadFromPLM")) | |
{ | |
var exportType = obj.GetNamedValue("ExportType"); | |
switch (exportType.ValueAsString) | |
{ | |
case "FILES": | |
{ | |
var fbd = new FolderBrowserDialog(); | |
if (fbd.ShowDialog() != DialogResult.OK) | |
return; | |
ExportFilesToFolder(fbd.SelectedPath, obj.GetAttribute("ExportData")); | |
} | |
break; | |
case "PDF": | |
{ | |
FolderBrowserDialog fbd = new FolderBrowserDialog(); | |
if (fbd.ShowDialog() != DialogResult.OK) | |
return; | |
ExportPDFToFolder(fbd.SelectedPath, obj.GetAttribute("ExportData")); | |
} | |
break; | |
case "CSV": | |
{ | |
var fileDialog = new SaveFileDialog() | |
{ | |
AddExtension = true, | |
AutoUpgradeEnabled = true, | |
Filter = "Файл разделенный табуляцией (*.csv)|*.csv|All files (*.*)|*.*", | |
DefaultExt = "csv", | |
FileName = fileName | |
}; | |
fileDialog.ShowDialog(); | |
try | |
{ | |
StreamWriter sw = new StreamWriter(fileDialog.FileName, false, Encoding.Unicode); | |
var exportDataAttr = obj.GetAttribute("ExportData"); | |
switch (obj.GetNamedValue("LevelType").ValueAsString) | |
{ | |
case "SINGLE": // "Уровень в одну колонку": | |
ExportAsSingleLevel(sw, exportDataAttr); | |
break; | |
case "MULTI": // "Подуровни в свои столбцы": | |
ExportAsMultiLevel(sw, exportDataAttr); | |
break; | |
} | |
sw.Close(); | |
} | |
catch { throw new FileNotFoundException("Файл не выбран"); } | |
} | |
break; | |
case "XLSX": | |
{ | |
var fileDialog = new SaveFileDialog() | |
{ | |
AddExtension = true, | |
AutoUpgradeEnabled = true, | |
Filter = "Книга Excel (*.xlsx)|*.xlsx", | |
DefaultExt = "xlsx", | |
FileName = fileName | |
}; | |
if (fileDialog.ShowDialog() == DialogResult.OK) | |
{ | |
var excel = new Excel(); | |
excel.Visible = false; | |
excel.CreateBook(); | |
excel.OpenWorksheet(1); | |
var exportDataAttr = obj.GetAttribute("ExportData"); | |
switch (obj.GetNamedValue("LevelType").ValueAsString) | |
{ | |
case "SINGLE": // "Уровень в одну колонку": | |
ExportAsSingleLevelExcel(excel, exportDataAttr); | |
break; | |
case "MULTI": // "Подуровни в свои столбцы": | |
ExportAsMultiLevelExcel(excel, exportDataAttr); | |
break; | |
} | |
excel.SaveAs(fileDialog.FileName); | |
excel.CloseBook(); | |
excel.Quit(); | |
excel.Kill(); | |
} | |
else { throw new FileNotFoundException("Файл не выбран"); } | |
} | |
break; | |
} | |
} // если не указана выгрузка, то создаём объекты в PLM. | |
else | |
{ | |
var parent = obj.GetInfoObject("Parent"); | |
var optionsDialog = new InfoObject(obj, @"InfoObjects\KB20.Unloading_str\Dialogs\GenDocs"); | |
if (Service.UI.ShowObjectProperties(optionsDialog, false)) | |
{ | |
bool genDocsExcel = optionsDialog.GetBoolean("GenDocsExcel"); | |
bool genDocsPrt = optionsDialog.GetBoolean("GenDocsPrt"); | |
bool genDocsPDF = optionsDialog.GetBoolean("GenDocsPDF"); | |
string date = DateTime.Now.ToShortDateString(); | |
//Формируем имя будущих файлов. | |
var pc = parent.GetInfoObject("ProductConfiguration"); | |
string name = pc.GetString("Name"); | |
string designation = pc.GetString("Designation"); | |
//Складываем Имя Документа. | |
var ordName = string.Format("{0} {1} {2}.xlsx", date, designation, name).Replace(':', '_'); | |
if (replaceDots) | |
ordName = ordName.Replace('.', '_'); | |
string path = Path.GetTempPath(); | |
path = Path.Combine(path, ordName); | |
var exportDataAttr = obj.GetAttribute("ExportData"); | |
if (genDocsExcel) | |
{ | |
Excel excel = new Excel(); | |
excel.Visible = false; | |
excel.CreateBook(); | |
excel.OpenWorksheet(1); | |
var attrDefs = exportDataAttr.SubItemTemplate.AttributeDefsModified.OrderBy(o => o.GroupKey); | |
int columnCounter = 1; | |
foreach (var attrDef in attrDefs) | |
{ | |
excel.SetCell(1, columnCounter, attrDef.NameUI); | |
int rowCounter = 2; | |
foreach (var ce in exportDataAttr.CollectionElements) | |
{ | |
excel.SetCell(rowCounter, columnCounter, ce[attrDef.NameKey] == null ? " " : ce[attrDef.NameKey].ToString()); | |
rowCounter++; | |
} | |
columnCounter++; | |
} | |
excel.SaveAs(path); | |
excel.CloseBook(); | |
excel.Quit(); | |
excel.Kill(); | |
UploadFile(path, obj); | |
File.Delete(path); | |
} | |
} | |
} | |
} | |
private void UploadFile(string path, InfoObject obj) | |
{ | |
var BaseDocTemplate = Service.GetTemplate(@"InfoObjects\STD\Documents\Document\TechnicalDocument"); | |
var BaseVerTemplate = Service.GetTemplate(@"InfoObjects\STD\Documents\DocumentVersion\TechnicalDocumentVersion"); | |
Template DocTemplate; | |
Template VerTemplate; | |
if (obj.Template != null && BaseDocTemplate != null && BaseVerTemplate != null) | |
{ | |
DocTemplate = BaseDocTemplate; | |
if (DocTemplate != null) | |
{ | |
VerTemplate = DocTemplate.GetCreatableTemplates(BaseVerTemplate).DefaultIfEmpty(BaseVerTemplate).FirstOrDefault(); | |
var parentFolder = obj.GetDataContainer("ParFolder"); | |
if (VerTemplate != null && parentFolder != null) | |
{ | |
using (Service.EnterNewGroupOperation()) | |
{ | |
var Doc = new InfoObject(parentFolder, DocTemplate); | |
var Ver = new InfoObject(Doc, VerTemplate); | |
var pc = obj.GetInfoObject("Parent.ProductConfiguration"); | |
Doc["ActualVersion"] = Ver; | |
Ver["DoNotGeneratePreview"] = true; | |
Ver["DocumentDesignation"] = pc["Designation"]; | |
Ver["ProductName"] = pc["Name"]; | |
Ver.GetAttribute("Body").Value.UploadFile(path); | |
Doc.IsBySystem = false; | |
Ver.IsBySystem = false; | |
Service.SaveChanges(); | |
} | |
} | |
} | |
} | |
} | |
private void ExportFilesToFolder(string root, EntityAttribute exportDataAttr) | |
{ | |
List<string> operNames = exportDataAttr.CollectionElements.Select(ce => ce.GetString("Oper_name")).Distinct().ToList(); | |
foreach (string operName in operNames) | |
{ | |
string opf = operName; | |
if (operName == "" || operName == null || operName == string.Empty) | |
opf = "Other"; | |
string cf = Path.Combine(root, opf); | |
if (!Directory.Exists(cf)) | |
Directory.CreateDirectory(cf); | |
List<object> versions = (from vr in exportDataAttr.CollectionElements | |
where vr["Oper_name"].ToString() == operName && vr["OriginalDocument"] != null | |
select vr["OriginalDocument"]).Distinct().ToList(); | |
foreach (InfoObject version in versions) | |
{ | |
FileDesc fd = version.GetFile("Body"); | |
Stream savestream = fd.DownloadingDataStream; | |
FileStream fs = File.Create(cf + "\\" + fd.OriginalName); | |
savestream.Copy(fs); | |
fs.Close(); | |
} | |
} | |
} | |
private void ExportPDFToFolder(string root, EntityAttribute exportDataAttr) | |
{ | |
string pdfDirectory = Path.Combine(root, "PDFs"); | |
if (!Directory.Exists(pdfDirectory)) | |
Directory.CreateDirectory(pdfDirectory); | |
// возьмём все атрибуты, где тип - ссылка на объект или список ссылок на объекты | |
var targetAttrs = exportDataAttr.SubItemTemplate.AttributeDefsModified.Where(ad => ad != null && (ad.DataType == AttributeDefBase.DataTypeEnum.LinkToInfoObject || ad.DataType == AttributeDefBase.DataTypeEnum.SetOfInfoObjectLinks)); | |
Set<InfoObject> ios = new Set<InfoObject>(); | |
foreach (var ce in exportDataAttr.CollectionElements) | |
{ | |
foreach (var attrDef in targetAttrs) | |
{ | |
var attr = ce.GetAttribute(attrDef); | |
if (attr == null || attr.IsEmpty) | |
continue; | |
if (attrDef.DataType == AttributeDefBase.DataTypeEnum.LinkToInfoObject) | |
{ | |
var io = attr.Value.Value as InfoObject; | |
if (io == null) | |
continue; | |
ios.AddOnce(io); | |
} | |
else if (attrDef.DataType == AttributeDefBase.DataTypeEnum.SetOfInfoObjectLinks) | |
ios.AddMany(attr.LinkedInfoObjects); | |
} | |
} | |
foreach (var io in ios) | |
{ | |
var body = io.GetFile("Body"); | |
if (body == null) | |
continue; | |
if (Path.GetExtension(body.OriginalName).ToUpper() == ".PDF") | |
{ | |
Stream savestream = body.DownloadingDataStream; | |
FileStream fs = File.Create(Path.Combine(pdfDirectory, body.OriginalName)); | |
savestream.Copy(fs); | |
fs.Close(); | |
savestream.Close(); | |
} | |
} | |
} | |
private bool ExportAsMultiLevelExcel(Excel xl, EntityAttribute ed) | |
{ | |
// 1 get max level | |
// 2 generate attrs list | |
// 3 write header | |
// 4 write data | |
int maxlevel = 0; | |
foreach (CollectionElement el in ed.CollectionElements) | |
{ | |
int curlevctr = el["Level"].SafeToString().Split(new Char[] { '.' }).Length; | |
if (maxlevel < curlevctr) | |
maxlevel = curlevctr; | |
} | |
//2 | |
List<string> attrnames = new List<string>(); | |
CollectionElement rootel = ed.CreateCollectionElement(); | |
var attrDefs = rootel.Template.AttributeDefsModified.OrderBy(o => o.GroupKey); | |
int cl = 1; | |
for (int i = 0; i < maxlevel; i++) | |
{ | |
xl.SetCell(1, cl, ("Уровень " + i.ToString())); | |
cl++; | |
} | |
foreach (var attrDef in attrDefs) | |
{ | |
if (attrDef.NameKey != "Level") | |
{ | |
attrnames.Add(attrDef.NameKey); | |
xl.SetCell(1, cl, attrDef.NameUI); | |
cl++; | |
} | |
} | |
//4 | |
/* | |
4.1 в цикле генерируем строку для записи в файл | |
4.1.1 генерация столбцов цровней | |
4.1.2 генерация атрибутов | |
4.1.3 запись строки | |
*/ | |
//4.1 | |
int rw = 2; | |
foreach (CollectionElement el in ed.CollectionElements) | |
{ | |
//4.1.1 | |
string[] levels = el["Level"].SafeToString().Split(new Char[] { '.' }); | |
cl = 1; | |
for (int i = 0; i < maxlevel; i++) | |
{ | |
if (i < levels.Length) | |
{ | |
xl.SetCell(rw, cl, levels[i]); | |
} | |
cl++; | |
} | |
//4.1.2 | |
foreach (string an in attrnames) | |
{ | |
xl.SetCell(rw, cl, (an == "Quantity" && el.GetFloat(an) == 0.0 ? "" : el[an].SafeToString())); | |
cl++; | |
} | |
rw++; | |
} | |
return true; | |
} | |
private bool ExportAsSingleLevelExcel(Excel xl, EntityAttribute ed) | |
{ | |
List<string> attrnames = new List<string>(); | |
CollectionElement rootel = ed.CreateCollectionElement(); | |
var attrDefs = rootel.Template.AttributeDefsModified.OrderBy(o => o.GroupKey); | |
int cl = 1; | |
foreach (var attrDef in attrDefs) | |
{ | |
attrnames.Add(attrDef.NameKey); | |
xl.SetCell(1, cl, attrDef.NameUI); | |
cl++; | |
} | |
cl = 1; | |
int rw = 2; | |
foreach (CollectionElement cel in ed.CollectionElements) | |
{ | |
cl = 1; | |
foreach (string attrname in attrnames) | |
{ | |
xl.SetCell(rw, cl, (attrname == "Quantity" && cel.GetFloat(attrname) == 0.0 ? "" : cel[attrname].SafeToString())); | |
cl++; | |
} | |
rw++; | |
} | |
return true; | |
} | |
private void ExportAsSingleLevel(StreamWriter sw, EntityAttribute ed) | |
{ | |
List<string> attrnames = new List<string>(); | |
CollectionElement rootel = ed.CreateCollectionElement(); | |
var attrDefs = rootel.Template.AttributeDefsModified.OrderBy(o => o.GroupKey); | |
string header = ""; | |
foreach (var attrDef in attrDefs) | |
{ | |
attrnames.Add(attrDef.NameKey); | |
header += attrDef.NameUI + "\t"; | |
} | |
sw.WriteLine(header); | |
foreach (CollectionElement cel in ed.CollectionElements) | |
{ | |
string data = ""; | |
foreach (string attrname in attrnames) | |
{ | |
data += (attrname == "Quantity" && cel.GetFloat(attrname) == 0.0 ? "" : cel[attrname].SafeToString()) + "\t"; | |
} | |
sw.WriteLine(data); | |
} | |
} | |
private void ExportAsMultiLevel(StreamWriter sw, EntityAttribute ed) | |
{ | |
// 1 get max level | |
// 2 generate attrs list | |
// 3 write header | |
// 4 write data | |
//1 | |
int maxlevel = 0; | |
foreach (CollectionElement el in ed.CollectionElements) | |
{ | |
int curlevctr = el["Level"].SafeToString().Split(new Char[] { '.' }).Length; | |
if (maxlevel < curlevctr) | |
maxlevel = curlevctr; | |
} | |
//2 | |
List<string> attrnames = new List<string>(); | |
CollectionElement rootel = ed.CreateCollectionElement(); | |
var attrDefs = rootel.Template.AttributeDefsModified.OrderBy(o => o.GroupKey); | |
string header = ""; | |
for (int i = 0; i < maxlevel; i++) | |
{ | |
header += ("Уровень" + i.ToString()) + "\t"; | |
} | |
foreach (var attrDef in attrDefs) | |
{ | |
if (attrDef.NameKey != "Level") | |
{ | |
attrnames.Add(attrDef.NameKey); | |
header += attrDef.NameUI + "\t"; | |
} | |
} | |
//3 | |
sw.WriteLine(header); | |
//4 | |
/* | |
4.1 в цикле генерируем строку для записи в файл | |
4.1.1 генерация столбцов уровней | |
4.1.2 генерация атрибутов | |
4.1.3 запись строки | |
*/ | |
//4.1 | |
foreach (CollectionElement el in ed.CollectionElements) | |
{ | |
string data = ""; | |
//4.1.1 | |
string[] levels = el["Level"].SafeToString().Split(new Char[] { '.' }); | |
for (int i = 0; i < maxlevel; i++) | |
{ | |
if (i < levels.Length) | |
{ | |
data += levels[i]; | |
} | |
data += "\t"; | |
} | |
//4.1.2 | |
foreach (string an in attrnames) | |
{ | |
data += (an == "Quantity" && el.GetFloat(an) == 0.0 ? "" : el[an].SafeToString()) + "\t"; | |
} | |
//4.1.3 | |
sw.WriteLine(data); | |
} | |
} | |
#region функции работы с Excel | |
// Выравнивание по горизонтали | |
public enum XlAlignHorizontal | |
{ | |
xlGeneral = 1, // По значению | |
xlLeft = -4131, // По левому краю (отступ) | |
xlCenter = -4108, // По центру | |
xlRight = -4152, // По правому краю (отступ) | |
xlFill = 5, // С заполнением | |
xlJustify = -4130, // По ширине | |
xlCenterAcrossSelection = 7, // По центру выделения | |
xlDistributed = -4117 // Распределенный (отступ) | |
} | |
// Выравнивание по вертикали | |
public enum XlAlignVertical | |
{ | |
xlTop = 1, // По верхнему краю | |
xlCenter = -4108, // По центру | |
xlBottom = -4107, // По нижнему краю | |
xlJustify = -4130, // По высоте | |
xlDistributed = -4117 // Распределенный | |
} | |
// Ориентация страницы | |
public enum XlPageOrientation | |
{ | |
xlPortrait = 1, //Книжный | |
xlLandscape = 2 // Альбомный | |
} | |
// Вид границы | |
public enum XlBordersIndex | |
{ | |
xlDiagonalDown = 5, // Border running from the upper left-hand corner to the lower right of each cell in the range. | |
xlDiagonalUp = 6, // Border running from the lower left-hand corner to the upper right of each cell in the range. | |
xlEdgeBottom = 9, // Border at the bottom of the range. | |
xlEdgeLeft = 7, // Border at the left-hand edge of the range. | |
xlEdgeRight = 10, // Border at the right-hand edge of the range. | |
xlEdgeTop = 8, // Border at the top of the range. | |
xlInsideHorizontal = 12, // Horizontal borders for all cells in the range except borders on the outside of the range. | |
xlInsideVertical = 11 // Vertical borders for all the cells in the range except borders on the outside of the range. | |
} | |
// Стиль линии для границы | |
public enum XlLineStyle | |
{ | |
xlContinuous = 1, // Continuous line. | |
xlDash = -4115, // Dashed line. | |
xlDashDot = 4, // Alternating dashes and dots. | |
xlDashDotDot = 5, // Dash followed by two dots. | |
xlDot = -4118, // Dotted line. | |
xlDouble = -4119, // Double line. | |
xlLineStyleNone = -4142, // No line. | |
xlSlantDashDot = 13 // Slanted dashes. | |
} | |
// Толщина линии границы | |
public enum XlBorderWeight | |
{ | |
xlHairline = 1, // Hairline (thinnest border). | |
xlMedium = -4138, // Medium. | |
xlThick = 4, // Thick (widest border). | |
xlThin = 2 // Thin. | |
} | |
// Расположение агрегации сгруппированных строк | |
public enum XlSummaryRow | |
{ | |
xlSummaryAbove = 0, // Сверху | |
xlSummaryBelow = 1 // Снизу | |
} | |
public class Excel : IDisposable | |
{ | |
object FExcel = null; | |
object FWorkbooks, FWorkbook, FWorksheets, FWorksheet, FRange; | |
// Конструктор | |
public Excel() | |
{ | |
FExcel = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application")); | |
} | |
// Деструктор | |
public void Dispose() | |
{ | |
try | |
{ | |
System.Runtime.InteropServices.Marshal.ReleaseComObject(FWorkbooks); | |
System.Runtime.InteropServices.Marshal.ReleaseComObject(FWorkbook); | |
System.Runtime.InteropServices.Marshal.ReleaseComObject(FWorksheets); | |
System.Runtime.InteropServices.Marshal.ReleaseComObject(FWorksheet); | |
System.Runtime.InteropServices.Marshal.ReleaseComObject(FRange); | |
System.Runtime.InteropServices.Marshal.ReleaseComObject(FExcel); | |
} | |
catch { } | |
finally | |
{ | |
FWorkbooks = null; | |
FWorkbook = null; | |
FWorksheets = null; | |
FWorksheet = null; | |
FRange = null; | |
FExcel = null; | |
} | |
System.GC.Collect(); | |
System.GC.WaitForPendingFinalizers(); | |
System.GC.Collect(); | |
System.GC.WaitForPendingFinalizers(); | |
} | |
public void Kill() | |
{ | |
int id; | |
var Hwnd = (int)FExcel.GetType().InvokeMember( | |
"Hwnd", System.Reflection.BindingFlags.GetProperty, null, FExcel, null); | |
GetWindowThreadProcessId(Hwnd, out id); | |
Process.GetProcessById(id).Kill(); | |
} | |
// Видимость | |
public bool Visible | |
{ | |
get | |
{ | |
return Convert.ToBoolean(FExcel.GetType().InvokeMember( | |
"Visible", System.Reflection.BindingFlags.GetProperty, null, FExcel, null)); | |
} | |
set | |
{ | |
FExcel.GetType().InvokeMember( | |
"Visible", System.Reflection.BindingFlags.SetProperty, null, FExcel, new object[] { value }); | |
} | |
} | |
// Формула ячейки | |
public void FormulaR1C1(string AAddress, object AFormula) | |
{ | |
FRange = FWorksheet.GetType().InvokeMember( | |
"Range", System.Reflection.BindingFlags.GetProperty, null, FWorksheet, new object[] { AAddress }); | |
FRange.GetType().InvokeMember( | |
"Activate", System.Reflection.BindingFlags.InvokeMethod, null, FRange, null); | |
object cellActive = FExcel.GetType().InvokeMember( | |
"ActiveCell", System.Reflection.BindingFlags.GetProperty, null, FExcel, null); | |
cellActive.GetType().InvokeMember( | |
"FormulaR1C1", System.Reflection.BindingFlags.SetProperty, null, cellActive, new object[] { AFormula }); | |
cellActive = null; | |
} | |
// Открыть книгу | |
public void OpenBook(string AFilePath) | |
{ | |
FWorkbooks = FExcel.GetType().InvokeMember( | |
"Workbooks", System.Reflection.BindingFlags.GetProperty, null, FExcel, null); | |
FWorkbook = FWorkbooks.GetType().InvokeMember( | |
"Open", System.Reflection.BindingFlags.InvokeMethod, null, FWorkbooks, new object[] { AFilePath, true }); | |
FWorksheets = FWorkbook.GetType().InvokeMember( | |
"Worksheets", System.Reflection.BindingFlags.GetProperty, null, FWorkbook, null); | |
FWorksheet = FWorksheets.GetType().InvokeMember( | |
"Item", System.Reflection.BindingFlags.GetProperty, null, FWorksheets, new object[] { 1 }); | |
} | |
// Выбрать страницу | |
public void OpenWorksheet(int AIndex) | |
{ | |
FWorksheet = FWorksheets.GetType().InvokeMember( | |
"Item", System.Reflection.BindingFlags.GetProperty, null, FWorksheets, new object[] { AIndex }); | |
} | |
// Создать книгу | |
public void CreateBook() | |
{ | |
FWorkbooks = FExcel.GetType().InvokeMember( | |
"Workbooks", System.Reflection.BindingFlags.GetProperty, null, FExcel, null); | |
FWorkbook = FWorkbooks.GetType().InvokeMember( | |
"Add", System.Reflection.BindingFlags.InvokeMethod, null, FWorkbooks, null); | |
FWorksheets = FWorkbook.GetType().InvokeMember( | |
"Worksheets", System.Reflection.BindingFlags.GetProperty, null, FWorkbook, null); | |
FWorksheet = FWorksheets.GetType().InvokeMember( | |
"Item", System.Reflection.BindingFlags.GetProperty, null, FWorksheets, new object[] { 1 }); | |
} | |
// Закрыть книгу | |
public void CloseBook() | |
{ | |
FWorkbook.GetType().InvokeMember( | |
"Close", System.Reflection.BindingFlags.InvokeMethod, null, FWorkbook, new object[] { false }); | |
} | |
// Закрыть приложение | |
public void Quit() | |
{ | |
FExcel.GetType().InvokeMember( | |
"Quit", System.Reflection.BindingFlags.InvokeMethod, null, FExcel, null); | |
} | |
// Сохранить как | |
public void SaveAs(string Path) | |
{ | |
FWorkbook.GetType().InvokeMember( | |
"SaveAs", System.Reflection.BindingFlags.InvokeMethod, null, FWorkbook, new object[] { Path }); | |
} | |
// Показать диалог предпросмотра печати | |
public void PrintPreview(bool EnableChanges) | |
{ | |
FWorkbook.GetType().InvokeMember( | |
"PrintPreview", System.Reflection.BindingFlags.InvokeMethod, null, FWorkbook, new object[] { EnableChanges }); | |
} | |
// Ширина столбца | |
public void ColumnWidth(string AAddress, double AWidth) | |
{ | |
FRange = FWorksheet.GetType().InvokeMember( | |
"Range", System.Reflection.BindingFlags.GetProperty, null, FWorksheet, new object[] { AAddress }); | |
FRange.GetType().InvokeMember( | |
"ColumnWidth", System.Reflection.BindingFlags.SetProperty, null, FRange, new object[] { AWidth }); | |
} | |
// Перенос строк | |
public void SetWrapText(string AAddress) | |
{ | |
FRange = FWorksheet.GetType().InvokeMember( | |
"Range", System.Reflection.BindingFlags.GetProperty, null, FWorksheet, new object[] { AAddress }); | |
FRange.GetType().InvokeMember( | |
"WrapText", System.Reflection.BindingFlags.SetProperty, null, FRange, new object[] { true }); | |
} | |
// Высота строки | |
public void RowHeight(string AAddress, double AHeight) | |
{ | |
FRange = FWorksheet.GetType().InvokeMember( | |
"Range", System.Reflection.BindingFlags.GetProperty, null, FWorksheet, new object[] { AAddress }); | |
FRange.GetType().InvokeMember( | |
"RowHeight", System.Reflection.BindingFlags.SetProperty, null, FRange, new object[] { AHeight }); | |
} | |
// Объединение ячеек | |
public void MergeCells(string AAddress) | |
{ | |
FRange = FWorksheet.GetType().InvokeMember( | |
"Range", System.Reflection.BindingFlags.GetProperty, null, FWorksheet, new object[] { AAddress }); | |
FRange.GetType().InvokeMember( | |
"Merge", System.Reflection.BindingFlags.InvokeMethod, null, FRange, null); | |
} | |
// Применение шрифта к ячейке | |
public void SetFont(string AAddress, Font AFont) | |
{ | |
FRange = FWorksheet.GetType().InvokeMember( | |
"Range", System.Reflection.BindingFlags.GetProperty, null, FWorksheet, new object[] { AAddress }); | |
object objFont = FRange.GetType().InvokeMember( | |
"Font", System.Reflection.BindingFlags.GetProperty, null, FRange, null); | |
objFont.GetType().InvokeMember( | |
"Size", System.Reflection.BindingFlags.SetProperty, null, objFont, new object[] { AFont.Size }); | |
objFont.GetType().InvokeMember( | |
"Bold", System.Reflection.BindingFlags.SetProperty, null, objFont, new object[] { AFont.Bold }); | |
objFont.GetType().InvokeMember( | |
"Name", System.Reflection.BindingFlags.SetProperty, null, objFont, new object[] { AFont.Name }); | |
//objFont.GetType().InvokeMember( | |
// "Height", System.Reflection.BindingFlags.SetProperty, null, objFont, new object[] { AFont.Height }); | |
objFont.GetType().InvokeMember( | |
"Strikethrough", System.Reflection.BindingFlags.SetProperty, null, objFont, new object[] { AFont.Strikeout }); | |
objFont = null; | |
} | |
// Применение шрифта к ячейке и цвета шрифта | |
public void SetFont(string AAddress, Font AFont, Color AColor) | |
{ | |
FRange = FWorksheet.GetType().InvokeMember( | |
"Range", System.Reflection.BindingFlags.GetProperty, null, FWorksheet, new object[] { AAddress }); | |
object objFont = FRange.GetType().InvokeMember( | |
"Font", System.Reflection.BindingFlags.GetProperty, null, FRange, null); | |
objFont.GetType().InvokeMember( | |
"Size", System.Reflection.BindingFlags.SetProperty, null, objFont, new object[] { AFont.Size }); | |
objFont.GetType().InvokeMember( | |
"Bold", System.Reflection.BindingFlags.SetProperty, null, objFont, new object[] { AFont.Bold }); | |
objFont.GetType().InvokeMember( | |
"Italic", System.Reflection.BindingFlags.SetProperty, null, objFont, new object[] { AFont.Italic }); | |
objFont.GetType().InvokeMember( | |
"Strikethrough", System.Reflection.BindingFlags.SetProperty, null, objFont, new object[] { AFont.Strikeout }); | |
objFont.GetType().InvokeMember( | |
"Name", System.Reflection.BindingFlags.SetProperty, null, objFont, new object[] { AFont.Name }); | |
//objFont.GetType().InvokeMember( | |
// "LineHeight", System.Reflection.BindingFlags.SetProperty, null, objFont, new object[] { AFont.Height }); | |
if (AColor != null) | |
{ | |
objFont.GetType().InvokeMember( | |
"Color", System.Reflection.BindingFlags.SetProperty, null, objFont, new object[] { AColor.ToArgb() }); | |
} | |
objFont = null; | |
} | |
// Применение цвета и способа заливки к ячейке | |
public void SetColor(string AAddress, int AColorIndex, int APatternIndex) | |
{ | |
FRange = FWorksheet.GetType().InvokeMember( | |
"Range", System.Reflection.BindingFlags.GetProperty, null, FWorksheet, new object[] { AAddress }); | |
object objInterior = FRange.GetType().InvokeMember( | |
"Interior", System.Reflection.BindingFlags.GetProperty, null, FRange, null); | |
objInterior.GetType().InvokeMember( | |
"ColorIndex", System.Reflection.BindingFlags.SetProperty, null, objInterior, new object[] { AColorIndex }); | |
objInterior.GetType().InvokeMember( | |
"Pattern", System.Reflection.BindingFlags.SetProperty, null, objInterior, new object[] { APatternIndex }); | |
objInterior = null; | |
} | |
// Установка ориентации страницы | |
public void SetOrientation(XlPageOrientation AOrientation) | |
{ | |
object pageSetup = FWorksheet.GetType().InvokeMember( | |
"PageSetup", System.Reflection.BindingFlags.GetProperty, null, FWorksheet, null); | |
pageSetup.GetType().InvokeMember( | |
"Orientation", System.Reflection.BindingFlags.SetProperty, null, pageSetup, new object[] { AOrientation }); | |
} | |
// Установка зума | |
public void SetZoom(int APercent) | |
{ | |
object pageSetup = FWorksheet.GetType().InvokeMember( | |
"PageSetup", System.Reflection.BindingFlags.GetProperty, null, FWorksheet, null); | |
pageSetup.GetType().InvokeMember( | |
"Zoom", System.Reflection.BindingFlags.SetProperty, null, pageSetup, new object[] { APercent }); | |
} | |
// Запись значения в ячейку | |
public void SetValue(string AAddress, string AValue) | |
{ | |
FRange = FWorksheet.GetType().InvokeMember( | |
"Range", System.Reflection.BindingFlags.GetProperty, null, FWorksheet, new object[] { AAddress }); | |
FRange.GetType().InvokeMember( | |
"Value", System.Reflection.BindingFlags.SetProperty, null, FRange, new object[] { AValue }); | |
} | |
public void SetCell(int row, int col, string value) | |
{ | |
object cells = FWorksheet.GetType().InvokeMember( | |
"Cells", System.Reflection.BindingFlags.GetProperty, null, (object)FWorksheet, new object[] { row, col }); | |
cells.GetType().InvokeMember( | |
"NumberFormat", System.Reflection.BindingFlags.SetProperty, null, cells, new object[] { "@" }); | |
cells.GetType().InvokeMember( | |
"Value", System.Reflection.BindingFlags.SetProperty, null, cells, new object[] { value }); | |
} | |
// Запись значения в ячейку с форматом | |
public void SetValue(string AAddress, string AValue, string AFormat) | |
{ | |
FRange = FWorksheet.GetType().InvokeMember( | |
"Range", System.Reflection.BindingFlags.GetProperty, null, FWorksheet, new object[] { AAddress }); | |
FRange.GetType().InvokeMember( | |
"NumberFormat", System.Reflection.BindingFlags.SetProperty, null, FRange, new object[] { AFormat }); | |
FRange.GetType().InvokeMember( | |
"Value", System.Reflection.BindingFlags.SetProperty, null, FRange, new object[] { AValue }); | |
} | |
// Запись значения в ячейку с форматом и культурой | |
public void SetValue(string AAddress, string AValue, string AFormat, CultureInfo ACulture) | |
{ | |
FRange = FWorksheet.GetType().InvokeMember( | |
"Range", System.Reflection.BindingFlags.GetProperty, null, FWorksheet, new object[] { AAddress }); | |
FRange.GetType().InvokeMember( | |
"NumberFormat", System.Reflection.BindingFlags.SetProperty, null, FRange, new object[] { AFormat }, ACulture); | |
FRange.GetType().InvokeMember( | |
"Value", System.Reflection.BindingFlags.SetProperty, null, FRange, new object[] { AValue }); | |
} | |
// Получить значение с ячейки | |
public string GetValue(string AAddress) | |
{ | |
FRange = FWorksheet.GetType().InvokeMember( | |
"Range", System.Reflection.BindingFlags.GetProperty, null, FWorksheet, new object[] { AAddress }); | |
return FRange.GetType().InvokeMember( | |
"Value", System.Reflection.BindingFlags.GetProperty, null, FRange, null).ToString(); | |
} | |
// Установка одной границы ячейки | |
public void SetCellBorder(string AAddress, XlBordersIndex AIndex, XlLineStyle ALineStyle, XlBorderWeight AWeight) | |
{ | |
FRange = FWorksheet.GetType().InvokeMember( | |
"Range", System.Reflection.BindingFlags.GetProperty, null, FWorksheet, new object[] { AAddress }); | |
object border = FRange.GetType().InvokeMember( | |
"Borders", System.Reflection.BindingFlags.GetProperty, null, FRange, new object[] { AIndex }); | |
border.GetType().InvokeMember( | |
"LineStyle", System.Reflection.BindingFlags.SetProperty, null, border, new object[] { ALineStyle }); | |
border.GetType().InvokeMember( | |
"Weight", System.Reflection.BindingFlags.SetProperty, null, border, new object[] { AWeight }); | |
border = null; | |
} | |
// Установка всех границ ячейки | |
public void SetCellBorderAll(string AAddress, XlBordersIndex[] AIndex, XlLineStyle[] ALineStyle, XlBorderWeight[] AWeight) | |
{ | |
for (int i = 0; i <= AIndex.Length - 1; i++) | |
this.SetCellBorder(AAddress, AIndex[i], ALineStyle[i], AWeight[i]); | |
} | |
// Установка всех границ диапазона ячеек | |
public void SetRangeBorders(string AAddress, XlLineStyle ALineStyle, XlBorderWeight AWeight) | |
{ | |
FRange = FWorksheet.GetType().InvokeMember( | |
"Range", System.Reflection.BindingFlags.GetProperty, null, FWorksheet, new object[] { AAddress }); | |
object borders = FRange.GetType().InvokeMember( | |
"Borders", System.Reflection.BindingFlags.GetProperty, null, FRange, new object[] { }); | |
borders.GetType().InvokeMember( | |
"LineStyle", System.Reflection.BindingFlags.SetProperty, null, borders, new object[] { ALineStyle }); | |
borders.GetType().InvokeMember( | |
"Weight", System.Reflection.BindingFlags.SetProperty, null, borders, new object[] { AWeight }); | |
borders = null; | |
} | |
// Установка границы вокруг диапазона ячеек | |
public void BorderAround(string AAddress, XlLineStyle ALineStyle, XlBorderWeight AWeight) | |
{ | |
FRange = FWorksheet.GetType().InvokeMember( | |
"Range", System.Reflection.BindingFlags.GetProperty, null, FWorksheet, new object[] { AAddress }); | |
FRange.GetType().InvokeMember( | |
"BorderAround", System.Reflection.BindingFlags.InvokeMethod, null, FRange, new object[] { ALineStyle, AWeight, 0, null }); | |
} | |
// Расположение агрегации сгруппированных строк | |
public void LocationSummaryRows(XlSummaryRow ASummaryRow) | |
{ | |
object sheet = FWorkbook.GetType().InvokeMember( | |
"ActiveSheet", System.Reflection.BindingFlags.GetProperty, null, FWorkbook, null); | |
object outline = sheet.GetType().InvokeMember( | |
"Outline", System.Reflection.BindingFlags.GetProperty, null, sheet, null); | |
outline.GetType().InvokeMember( | |
"SummaryRow", System.Reflection.BindingFlags.SetProperty, null, outline, new object[] { ASummaryRow }); | |
} | |
// Группировка строк | |
public void GroupRows(string AAddress, bool AIsGrouping) | |
{ | |
FRange = FWorksheet.GetType().InvokeMember( | |
"Range", System.Reflection.BindingFlags.GetProperty, null, FWorksheet, new object[] { AAddress }); | |
object rows = FRange.GetType().InvokeMember( | |
"Rows", System.Reflection.BindingFlags.GetProperty, null, FRange, null); | |
if (AIsGrouping) | |
rows.GetType().InvokeMember("Group", System.Reflection.BindingFlags.GetProperty, null, rows, null); | |
else | |
rows.GetType().InvokeMember("Ungroup", System.Reflection.BindingFlags.GetProperty, null, rows, null); | |
rows = null; | |
} | |
// Группировка столбцов | |
public void GroupColumns(string AAddress, bool AIsGrouping) | |
{ | |
FRange = FWorksheet.GetType().InvokeMember( | |
"Range", System.Reflection.BindingFlags.GetProperty, null, FWorksheet, new object[] { AAddress }); | |
object columns = FRange.GetType().InvokeMember("Columns", System.Reflection.BindingFlags.GetProperty, null, FRange, null); | |
if (AIsGrouping) | |
columns.GetType().InvokeMember("Group", System.Reflection.BindingFlags.GetProperty, null, columns, null); | |
else | |
columns.GetType().InvokeMember("Ungroup", System.Reflection.BindingFlags.GetProperty, null, columns, null); | |
} | |
// Выравнивание по горизонтали | |
public void AlignHorizontal(string AAddress, XlAlignHorizontal AAlign) | |
{ | |
FRange = FWorksheet.GetType().InvokeMember( | |
"Range", System.Reflection.BindingFlags.GetProperty, null, FWorksheet, new object[] { AAddress }); | |
FRange.GetType().InvokeMember( | |
"HorizontalAlignment", System.Reflection.BindingFlags.SetProperty, null, FRange, new object[] { AAlign }); | |
} | |
// Выравнивание по вертикали | |
public void AlignVertical(string AAddress, XlAlignVertical AAlign) | |
{ | |
FRange = FWorksheet.GetType().InvokeMember( | |
"Range", System.Reflection.BindingFlags.GetProperty, null, FWorksheet, new object[] { AAddress }); | |
FRange.GetType().InvokeMember( | |
"VerticalAlignment", System.Reflection.BindingFlags.SetProperty, null, FRange, new object[] { AAlign }); | |
} | |
// Вертикальный разрыв страницы | |
public void PageBreakerVertical(string AAddress) | |
{ | |
FRange = FWorksheet.GetType().InvokeMember( | |
"Range", System.Reflection.BindingFlags.GetProperty, null, FWorksheet, new object[] { AAddress }); | |
object pageBreak = FWorksheet.GetType().InvokeMember( | |
"VPageBreaks", System.Reflection.BindingFlags.GetProperty, null, FWorksheet, null); | |
pageBreak.GetType().InvokeMember( | |
"Add", System.Reflection.BindingFlags.InvokeMethod, null, pageBreak, new object[] { FRange }); | |
pageBreak = null; | |
} | |
// Горизонтальный разрыв страницы | |
public void PageBreakerHorizontal(string AAddress) | |
{ | |
FRange = FWorksheet.GetType().InvokeMember( | |
"Range", System.Reflection.BindingFlags.GetProperty, null, FWorksheet, new object[] { AAddress }); | |
object pageBreak = FWorksheet.GetType().InvokeMember( | |
"HPageBreaks", System.Reflection.BindingFlags.GetProperty, null, FWorksheet, null); | |
pageBreak.GetType().InvokeMember( | |
"Add", System.Reflection.BindingFlags.InvokeMethod, null, pageBreak, new object[] { FRange }); | |
pageBreak = null; | |
} | |
// Получить имя столбца по номеру | |
// (1 = A, 2 = B...27 = AA...703 = AAA...) | |
public static string GetColNameFromIndex(int columnNumber) | |
{ | |
int dividend = columnNumber; | |
string columnName = String.Empty; | |
int modulo; | |
while (dividend > 0) | |
{ | |
modulo = (dividend - 1) % 26; | |
columnName = Convert.ToChar(65 + modulo).ToString() + columnName; | |
dividend = (int)((dividend - modulo) / 26); | |
} | |
return columnName; | |
} | |
// Получить номер стобца по имени | |
// (A = 1, B = 2...AA = 27...AAA = 703...) | |
public static int GetColNumberFromName(string columnName) | |
{ | |
char[] characters = columnName.ToUpperInvariant().ToCharArray(); | |
int sum = 0; | |
for (int i = 0; i < characters.Length; i++) | |
{ | |
sum *= 26; | |
sum += (characters[i] - 'A' + 1); | |
} | |
return sum; | |
} | |
// Автоматическое выравнивание размеров столбцов | |
public void AutoFit(string AAddress) | |
{ | |
FRange = FWorksheet.GetType().InvokeMember( | |
"Range", System.Reflection.BindingFlags.GetProperty, null, FWorksheet, new object[] { AAddress }); | |
object cols = FRange.GetType().InvokeMember("Columns", System.Reflection.BindingFlags.GetProperty, null, FRange, null); | |
cols.GetType().InvokeMember("AutoFit", System.Reflection.BindingFlags.InvokeMethod, null, cols, null); | |
cols = null; | |
} | |
} | |
[System.Runtime.InteropServices.DllImport("user32.dll")] | |
static extern int GetWindowThreadProcessId(int hWnd, out int lpdwProcessId); | |
#endregion | |
/// <summary> | |
/// Нотификация об изменении какого-либо атрибута объекта | |
/// </summary> | |
/// <param name="obj">Объект, чей атрибут изменился</param> | |
/// <param name="attr">Собственно изменившийся атрибут либо null, если изменилось сразу много атрибутов</param> | |
/// <remarks>Метод вызывается по месту изменения значения атрибута. Это может происходить как на клиенте, | |
/// так и на сервере. В том числе внутри обработки операции сохранения, где вложенные вызовы сохранения | |
/// заблокированы (приводят к исключению). | |
/// Метод вызывается в порядке от родителей к детям-модификаторам </remarks> | |
public override void OnAttributeChanged(InfoObject obj, EntityAttribute attr) | |
{ | |
bool inited = obj.GetBoolean("InitFinished"); | |
if (!inited) | |
return; | |
// Изменения атрибутов в ходе обработки операции сохранения или просто на сервере | |
// обычно не требуют дополнительной обработки. завершаем метод в этом случае. | |
if (Service.IsInSaveProcessing || Service.RunningOnServer || Service.IsImportOperation) | |
return; | |
if (attr.NameKey == "Multiplicate" || attr.NameKey == "NotSetLevelAndQuantityForRootAssy") | |
UpdateItemList(obj); | |
} | |
// AA Отсюда начинается формирование непосредственно самих значений атрибутов | |
// АА Выше - функции экспорта-импорта в Excel и др. | |
Dictionary<string, string[]> attrNamesDict; | |
EntityAttribute exportDataAttr; | |
StringBuilder errors; | |
bool multiply, setRootLevel; | |
// StringBuilder debug_; | |
// AA ExportDialog - переменная для инф. объекта ExportDialogDev (Выгрузка разраб.) | |
private void UpdateItemList(InfoObject exportDialog) | |
{ | |
// АА коллекция атрибутируемых элементов | |
exportDataAttr = exportDialog.GetAttribute("ExportData"); | |
exportDataAttr.CollectionElements.Clear(); | |
attrNamesDict = new Dictionary<string, string[]>(); | |
errors = new StringBuilder(); | |
/* АА ExportDialog: UnloadFromPLM, Name, LevelType, ExportType, Parent, ParFolder и др. */ | |
// АА Умножать количество деталей на количество подсборок (да/нет) | |
multiply = exportDialog.GetBoolean("Multiplicate"); | |
// АА Не устанавливать количество и уровень для корневой сборки (да/нет) | |
setRootLevel = !exportDialog.GetBoolean("NotSetLevelAndQuantityForRootAssy"); | |
// АА Assy - Assembly | |
// АА ссылка на информационный объект "Родитель" | |
var pvc = exportDialog.GetInfoObject("Parent"); | |
//вывод всех атрибутов родителя | |
//errors.Append(string.Join(", ", pvc.AllAttributes)); | |
// проверка на бесконечный цикл | |
var callerChain = new Stack<TID>(); | |
callerChain.Push(pvc.Id); | |
// наличие этого объекта означает, что есть цикл | |
var looper = CheckLoop(pvc, callerChain); | |
if (looper == null) | |
{ | |
// наполняем словарь ключей атрибутов с добавление массива тэгов | |
foreach (var attrDef in exportDataAttr.SubItemTemplate.AttributeDefsModified){ | |
attrNamesDict.Add(attrDef.NameKey, attrDef.Tags.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)); | |
}; | |
/* АА Вывод для значений массива для дебага*/ | |
/* foreach (var attrDef in exportDataAttr.SubItemTemplate.AttributeDefsModified) | |
{ | |
errors.AppendLine($"{attrDef} ({attrDef.NameKey}) : {attrDef.Tags};"); | |
} | |
*/ | |
// string result = string.Join(", ", attrNamesDict); | |
//string dictAsString = string.Join(Environment.NewLine, attrNamesDict.Select(kv => $"{kv.Key}: [{string.Join(", ", kv.Value)}]")); | |
// errors.Append(dictAsString); | |
var rootLevel = setRootLevel ? "0" : ""; | |
var rootQuant = setRootLevel ? -1 : 0; | |
// заполняем таблицу | |
FillItems(pvc, null, rootQuant, rootLevel, true); | |
} | |
else | |
errors.AppendLine("Предупреждение! Обнаружен <font color=\"Green\"> бесконечный цикл </font> в ИИВ <a href=\"" + Service.UI.FormatLink((ScriptingObject)looper, true) + "\">" + looper.ToString() + "</a>. Обновление списка не возможно. <br>"); | |
if (errors.Length > 0) | |
{ | |
Form rep = new Form(); | |
WebBrowser br = new WebBrowser(); | |
br.Parent = rep; | |
br.Dock = DockStyle.Fill; | |
br.DocumentText = errors.ToString(); | |
rep.ShowDialog(); | |
} | |
} | |
private InfoObject CheckLoop(InfoObject target, Stack<TID> callerChain) | |
{ | |
if (target == null) | |
return null; | |
InfoObject looper = null; | |
foreach (var product in target.GetCollectionElements("Items").Safe().Select(ce => ce.GetInfoObject("ProductItem")).SkipNull()) | |
{ | |
if (callerChain.Contains(product.Id)) | |
looper = target; | |
// выход из цикла при первоначальном нахождении лупера | |
if (looper != null) | |
break; | |
callerChain.Push(product.Id); | |
looper = CheckLoop(product, callerChain); | |
callerChain.Pop(); | |
// точка выныривания из рекурсии | |
if (looper != null) | |
break; | |
} | |
return looper; | |
} | |
// FillItems(pvc, null, rootQuant, rootLevel, true) вызов из UpdateItemList; | |
private void FillItems(InfoObject pvc, CollectionElement sourceElement, double quantity, string level, bool isRoot) | |
{ | |
if (pvc == null) | |
{ | |
var parent = sourceElement == null ? null : sourceElement.OwnerObject as InfoObject; | |
errors.AppendLine(string.Format("Предупреждение! <font color=\"Green\"> Отсутствует изделие </font>{0}. Получение атрибутов для данной записи невозможно. <br>", | |
parent == null ? "" : "в составе <a href =\"" + Service.UI.FormatLink((ScriptingObject)parent, true) + "\">" + parent.ToString() + "</a>")); | |
return; | |
} | |
var productConfiguration = pvc.GetInfoObject("ProductConfiguration"); | |
var productVersion = pvc.GetInfoObject("ProductVersion"); | |
// AA Родитель-изделие для версии изделия | |
var izdelie = productVersion.GetInfoObject("LinkToOriginalObject"); | |
// АА Получение доступа к контейнеру ЭРИ Изделия | |
var ParentContainer = izdelie.ContainerOriginal; | |
var parameters = ParentContainer.GetAttribute("Parameters"); | |
StringBuilder parameters_string = new StringBuilder(); | |
var FSCValue = "Не указано"; | |
var PN_MentorValue = "Не указано"; | |
var ManufacturerValue = "Не указано"; | |
var OriginalContainer = ParentContainer.ToString(); | |
var nameIzdelie = izdelie.GetString("Name"); | |
Dictionary<string, string> calculatedAttrs = new Dictionary<string, string>(); | |
foreach (var item in parameters.CollectionElements) { | |
string attrName = item.GetString("NameInStandard"); | |
if (attrName == "FSC" || attrName == "P/N Mentor" || attrName == "Производитель") | |
{ | |
calculatedAttrs[attrName] = item.GetString("NameKeyTable"); | |
//parameters_string.Append($"{attrName}: {calculatedAttrs[attrName]} "); | |
} | |
} | |
// OK | |
// parameters_string.Append($"FSC: {fsc_attr}; PN Mentor: {pn_mentor_attr}"); | |
// | |
bool collectMode = false; | |
foreach (var param in ParentContainer.AllAttributes){ | |
if (param.NameKey == "Name" && param.Value.ValueAsString == nameIzdelie){ | |
collectMode = true; | |
} | |
if (collectMode && param.NameKey != "Order"){ | |
if (calculatedAttrs["FSC"] == param.NameKey){ | |
FSCValue = param.Value.ValueAsString; | |
}else if (calculatedAttrs["P/N Mentor"] == param.NameKey){ | |
PN_MentorValue = param.Value.ValueAsString; | |
}else if (calculatedAttrs["Производитель"] == param.NameKey){ | |
ManufacturerValue = param.Value.ValueAsString; | |
} | |
}else{ | |
collectMode = false; | |
} | |
} | |
collectMode = false; | |
var allAttributes = ParentContainer.AllAttributes.ToList(); | |
for (int i = allAttributes.Count - 1; i >= 0; i--) { | |
var param = allAttributes[i]; | |
if (param.NameKey == "Name" && param.Value.ValueAsString == nameIzdelie){ | |
collectMode = true; | |
} | |
if (collectMode && param.NameKey != "Order"){ | |
if (calculatedAttrs["FSC"] == param.NameKey){ | |
FSCValue = param.Value.ValueAsString; | |
}else if (calculatedAttrs["P/N Mentor"] == param.NameKey){ | |
PN_MentorValue = param.Value.ValueAsString; | |
}else if (calculatedAttrs["Производитель"] == param.NameKey){ | |
ManufacturerValue = param.Value.ValueAsString; | |
} | |
}else{ | |
collectMode = false; | |
} | |
} | |
collectMode = false; | |
//Service.UI.ShowMessage(string.Join(", ", parameters_string)); | |
/*bool collectMode = false; | |
bool orderMet = false; | |
foreach (var param in ParentContainer.AllAttributes) { | |
if (param.NameKey == "Name" && param.Value.ValueAsString == nameIzdelie) | |
{ | |
collectMode = true; | |
continue; | |
} | |
if (collectMode) { | |
if (param.NameKey == "Order") | |
{ | |
orderMet = true; | |
break; | |
} | |
if (calculatedAttrs.ContainsValue(param.NameKey)) | |
{ | |
if (param.NameKey == calculatedAttrs["FSC"]) | |
{ | |
FSCValue = param.Value.ValueAsString; | |
} | |
if (param.NameKey == calculatedAttrs["P/N Mentor"]) | |
{ | |
PN_MentorValue = param.Value.ValueAsString; | |
} | |
if (param.NameKey == calculatedAttrs["Производитель"]) | |
{ | |
ManufacturerValue = param.Value.ValueAsString; | |
} | |
} | |
} | |
} | |
if (!orderMet) { | |
for (int i = ParentContainer.AllAttributes.Count() - 1; i >= 0; i--) | |
{ | |
var param = ParentContainer.AllAttributes.ElementAt(i); | |
if (param.NameKey == "Order") | |
{ | |
break; | |
} | |
if (calculatedAttrs.ContainsValue(param.NameKey)) | |
{ | |
if (param.NameKey == calculatedAttrs["FSC"]) | |
{ | |
FSCValue = param.Value.ValueAsString; | |
} | |
if (param.NameKey == calculatedAttrs["P/N Mentor"]) | |
{ | |
PN_MentorValue = param.Value.ValueAsString; | |
} | |
if (param.NameKey == calculatedAttrs["Производитель"]) | |
{ | |
ManufacturerValue = param.Value.ValueAsString; | |
} | |
} | |
} | |
} | |
Service.UI.ShowMessage(string.Join(", ", parameters_string)); | |
//parameters_string.Append($"FSC: {FSCValue} PN Mentor: {PN_MentorValue} Manuf.: {ManufacturerValue}"); | |
// Clipboard.SetText(parameters_string.ToString()); | |
/* | |
foreach (var param in ParentContainer.AllAttributes) | |
{ | |
if (param.NameKey.Contains("attr") || param.NameKey.Contains("Name") || param.NameKey.Contains("Order")){ | |
parameters_string.Append($"{param.NameKey} : {param.Value.Value}"); | |
} | |
if (param.NameKey == "Name" && param.Value.ValueAsString == nameIzdelie) | |
{ | |
attrReadMode = true; | |
} | |
if (attrReadMode && param.NameKey == "Order") | |
{ | |
attrReadMode = false; | |
break; | |
} | |
if (attrReadMode && calculatedAttrs.ContainsValue(param.NameKey)) | |
{ | |
if (param.NameKey == calculatedAttrs["FSC"]) | |
{ | |
FSCValue = param.Value.ValueAsString; | |
} | |
if (param.NameKey == calculatedAttrs["P/N Mentor"]) | |
{ | |
PN_MentorValue = param.Value.ValueAsString; | |
} | |
if (param.NameKey == calculatedAttrs["Производитель"]) | |
{ | |
ManufacturerValue = param.Value.ValueAsString; | |
} | |
} | |
} | |
Clipboard.SetText(parameters_string.ToString()); | |
for (int i = ParentContainer.AllAttributes.Count() - 1; i >= 0; i--) { | |
var param = ParentContainer.AllAttributes.ElementAt(i); | |
if (param.NameKey == "Name" && param.Value.ValueAsString == nameIzdelie) { | |
attrReadMode = true; | |
} | |
if (attrReadMode && param.NameKey == "Order") { | |
attrReadMode = false; | |
} | |
if (attrReadMode && calculatedAttrs.ContainsValue(param.NameKey)) | |
{ | |
if (param.NameKey == calculatedAttrs["FSC"]) | |
{ | |
FSCValue = param.Value.ValueAsString; | |
} | |
if (param.NameKey == calculatedAttrs["P/N Mentor"]) | |
{ | |
PN_MentorValue = param.Value.ValueAsString; | |
} | |
if (param.NameKey == calculatedAttrs["Производитель"]) | |
{ | |
ManufacturerValue = param.Value.ValueAsString; | |
} | |
} | |
} | |
//parameters_string.Append($"{FSCValue}, {PN_MentorValue}, {ManufacturerValue}"); | |
//Service.UI.ShowMessage(string.Join(", ", parameters_string)); | |
/* | |
var fsc_inner_value = ""; | |
var pn_mentor_inner_value = ""; | |
foreach (var param in ParentContainer.AllAttributes) { | |
parameters_string.Append($"{param.NameKey}: {param.Value.Value} "); | |
if (param.NameKey == fsc_attr){ | |
fsc_inner_value = param.Value.Value.ToString(); | |
} | |
if (param.NameKey == pn_mentor_attr){ | |
pn_mentor_inner_value = param.Value.Value.ToString(); | |
} | |
if (param.NameKey == "Name" && param.Value.Value.ToString() == nameIzdelie){ | |
if (fsc_inner_value != ""){ | |
FSCValue = fsc_inner_value; | |
} | |
if (pn_mentor_inner_value != ""){ | |
PN_MentorValue = pn_mentor_inner_value; | |
} | |
fsc_inner_value = ""; | |
pn_mentor_inner_value = ""; | |
} | |
} */ | |
var documentVersion = pvc.GetInfoObject("ProductVersion.OriginalDocument"); | |
var newCE = exportDataAttr.AddCollectionElement(); | |
if (!isRoot || setRootLevel) | |
newCE["Quantity"] = quantity; | |
newCE["ProductItem"] = pvc; | |
newCE["OriginalDocument"] = documentVersion; | |
newCE["Level"] = level; | |
newCE["FSC"] = FSCValue; | |
newCE["PN_Mentor"] = PN_MentorValue; | |
newCE["OriginalContainer"] = OriginalContainer; | |
newCE["Manufacturer"] = ManufacturerValue; | |
// определения атрибутов, которые будут заполняться вручную | |
var manualyHandledAttributes = new[] { "Quantity", "Level", "ProductItem", "OriginalDocument", | |
"FSC", "PN_Mentor", "OriginalContainer", "Manufacturer"}; | |
// AA attrNamesDict - словарь ключей из моей коллекции атрибутов "Экспортируемые элементы" | |
foreach (var kvp in attrNamesDict) | |
{ | |
var attrName = kvp.Key; | |
var attrTags = kvp.Value; | |
// АА Этим можно вывести "Part Number" из коллекции Экспорт. элементы | |
// errors.AppendLine($"{attrName} |"); | |
// пропустим ручные атрибуты | |
if (manualyHandledAttributes.Contains(attrName)) | |
continue; | |
// пропустим авторассчётные атрибуты чтоб они сами считались | |
// AA Авторассчётные атрибуты - те, которые имеют включённое автовычисление и собств. скрипт (подлинник STEP и подлинник PDF) | |
if (newCE.GetAttributeDef(attrName).AutoCalculationKind == AttributeDefBase.AutoCalculationKindEnum.Calculating) | |
{ | |
newCE.GetAttribute(attrName).TurnToCalculated(); | |
continue; | |
} | |
if (newCE.GetAttributeDef(attrName).AutoCalculationKind != AttributeDefBase.AutoCalculationKindEnum.None){ | |
continue; | |
} | |
IAttributableObject valueSource = pvc; | |
// если в тэгах содержится ключевое слово, то нужно использовать другой источник данных | |
if (attrTags.Any(str => str.StartsWith("DataSource"))) | |
{ | |
var sourceString = attrTags.First(str => str.StartsWith("DataSource")); | |
if (sourceString.Contains("Version")) | |
valueSource = productVersion; | |
else if (sourceString.Contains("Configuration")) | |
valueSource = productConfiguration; | |
else if (sourceString.Contains("Element") && sourceElement != null) | |
valueSource = sourceElement; | |
} | |
if (valueSource == null) | |
errors.AppendLine("<font color=\"Yellow\">Предупреждение!</font> атрибут <font color=\"Green\">" + attrName + "</font> не может быть выгружен из ИИВ <a href=\"" + Service.UI.FormatLink((ScriptingObject)pvc, true) + "\">" + pvc.ToString() + "</a> с тэгами <font color=\"Green\">" + attrTags.ToString() + "</font> <br>"); | |
else{ | |
newCE[attrName] = valueSource[attrName]; | |
} | |
} | |
int levelCounter = 1; | |
// АА песочница с выводом функций и атрибутов элемента | |
/* | |
foreach (var itemz in pvc.GetCollectionElements("Items")) { | |
errors.Append(itemz.GetString("Part_Number")); | |
} | |
*/ | |
foreach (var item in pvc.GetCollectionElements("Items").Safe().OrderBy(ce=>ce.GetString("SortedKey"))) | |
{ | |
// aa | |
// item - это Name + Quantity | |
var childQuantity = item.GetDouble("Quantity"); | |
/* | |
if (item.ToString().Contains("C331")){ | |
errors.Append(item); | |
} | |
*/ | |
if (!isRoot && multiply) | |
childQuantity *= quantity; | |
var childLevel = string.Format("{0}{1}", isRoot ? "" : level + ".", levelCounter++.ToString()); | |
// errors.Append(string.Join(", ", item.GetInfoObject("ProductItem").AllAttributes)); | |
// АА Эта часть заполняет данными в интерфейсе | |
FillItems(item.GetInfoObject("ProductItem"), item, childQuantity, childLevel, false); | |
} | |
} | |
/// <summary> | |
/// Возвращает запрошенное представление объекта в UI. | |
/// </summary> | |
/// <param name="obj">Объект для которого требуется UI представление</param> | |
/// <param name="dataKind">Запрашиваемый вид данных (название, иконки, превью)</param> | |
/// <param name="context">Контекст вызова для доступа к списку формируемых дополнительных иконок</param> | |
/// <returns>null если следует использовать вариант по умолчанию, | |
/// String для названий объекта (форматированный HTML тэгами для NameDetails и RichName), | |
/// CustomIcon (или строковый ключ иконки в общем ImageListе) и AdditionalIcon[] или CustomIcon[] (или массив ключей) для иконок, | |
/// Image (или BlobDesc) для превью, | |
/// Color для раскраски элементов в дереве и списке, | |
/// FontStyle для указания стиля шрифта в дереве и списке</returns> | |
/// <remarks> Вызывается в основном клиентским UI кодом. | |
/// Название объекта может запрашиваться и серверным кодом. | |
/// Исключения, вышедшие их этого метода, отправляются в серверный отчет об ошибке без показа сообщения пользователю.</remarks> | |
public override Object GetUIData( InfoObject obj, AttributableDataObject.UIDataKind dataKind, UIDataInvokeContext context ) | |
{ | |
switch( dataKind ) | |
{ | |
// Имя по умолчанию | |
case AttributableDataObject.UIDataKind.Name: | |
break; | |
// Хранимое в базе имя | |
case AttributableDataObject.UIDataKind.NameForSearchInDb: | |
break; | |
// Прочие имена для разных контекстов использования | |
case AttributableDataObject.UIDataKind.NameForTreeView: | |
case AttributableDataObject.UIDataKind.NameForListView: | |
case AttributableDataObject.UIDataKind.NameForSearchResultListView: | |
case AttributableDataObject.UIDataKind.NameForHyperlink: | |
case AttributableDataObject.UIDataKind.NameForHyperlinkInGrid: | |
case AttributableDataObject.UIDataKind.NameForMultiLine: | |
break; | |
// Форматированная HTML тэгами строка - заголовок карточки объекта | |
case AttributableDataObject.UIDataKind.RichName: | |
break; | |
// Форматированная HTML тэгами строка, дополняющая название объекта в дереве | |
case AttributableDataObject.UIDataKind.NameDetails: | |
break; | |
case AttributableDataObject.UIDataKind.Tooltip: | |
// Текстовая строка всплывающей подсказки | |
break; | |
case AttributableDataObject.UIDataKind.MainIcon: | |
case AttributableDataObject.UIDataKind.MainIconForHyperLink: | |
case AttributableDataObject.UIDataKind.MainIconForHyperLinkInGrid: | |
// Следует вернуть или существующий объект CustomIcon или | |
// строковый ключ иконки в системном ImageList клиента. | |
// См. Service.UI.ImageListManager | |
break; | |
case AttributableDataObject.UIDataKind.MainOverlayIcon: | |
case AttributableDataObject.UIDataKind.MainOverlayIconForHyperLink: | |
case AttributableDataObject.UIDataKind.MainOverlayIconForHyperLinkInGrid: | |
// Следует вернуть или существующий объект CustomIcon или | |
// строковый ключ иконки в системном ImageList клиента. | |
// См. Service.UI.ImageListManager | |
break; | |
case AttributableDataObject.UIDataKind.AdditionalIcons: | |
// Дополнительные иконки складываются со всех родительских шаблонов в упорядоченное множество context.AdditionalIcons. | |
// Следует вернуть массив AdditionalIcon с настроенными ключами, изображением, всплывающей подсказкой и параметрами сортировки. | |
// Либо устаревший вариант: вернуть или IEnumerable<CustomIcon> существующих объектов CustomIcon или | |
// IEnumerable<String> строковых ключей иконок в системном ImageList клиента. | |
// См. Service.UI.ImageListManager | |
// Также можно вернуть IEnumerable< KeyValuePair<String, String|CustomIcon|Object> >. В этом случае | |
// результирующий набор иконок формируется по таким правилам: | |
// Сначала идут иконки с разными ключами (KeyValuePair.Key), сортированные по возрастанию этого ключа. | |
// Затем идут иконки с пустыми (или не указанными) ключами в порядке добавления (от родительских шаблонов к дочерним) | |
break; | |
case AttributableDataObject.UIDataKind.AdditionalIconsForListView: | |
case AttributableDataObject.UIDataKind.AdditionalIconsForHyperLink: | |
case AttributableDataObject.UIDataKind.AdditionalIconsForHyperLinkInGrid: | |
// См. AdditionalIcons | |
// По умолчанию используются AdditionalIcons | |
break; | |
case AttributableDataObject.UIDataKind.Preview: | |
// Следует вернуть или BlobDesc с бинарными данными изображения, либо объект Image | |
break; | |
case AttributableDataObject.UIDataKind.ColorForTreeView: | |
case AttributableDataObject.UIDataKind.ColorForListView: | |
case AttributableDataObject.UIDataKind.ColorForHyperLink: | |
case AttributableDataObject.UIDataKind.ColorForHyperLinkInGrid: | |
// Следует вернуть значение типа Color | |
break; | |
case AttributableDataObject.UIDataKind.FontStyleForTreeView: | |
case AttributableDataObject.UIDataKind.FontStyleForListView: | |
// Следует вернуть значение типа FontStyle | |
break; | |
case AttributableDataObject.UIDataKind.PropertiesWindowTitle: | |
// Заголовок плавающего окна с карточкой объекта | |
break; | |
} | |
return null; | |
} | |
/// <summary> | |
/// Возвращает список виртуальных определений атрибутов для отображения в карточке объекта | |
/// </summary> | |
/// <param name="obj">Объект, для которого запрашиваются виртуальные атрибуты</param> | |
/// <param name="defs">Список добавленных виртуальных определений атрибутов</param> | |
/// <remarks>Вызывается в порядке от родительских шаблонов к дочерним и модификаторам</remarks> | |
public override void GetVirtualAttributeDefs( InfoObject obj, List<AttributeDefVirtual> defs ) | |
{ | |
//var def = new AttributeDefVirtual( obj.Template, "p1", "Название атрибута", AttributeDefBase.DataTypeEnum.Text ); | |
//def.DisplayType = AttributeDefBase.DisplayTypeEnum.TextBox; | |
//def.PageNameKey = "Main"; | |
//defs.Add( def ); | |
} | |
/// <summary> | |
/// Вызывается клиентским кодом UI перед показом карточки объекта. | |
/// </summary> | |
/// <param name="obj">Объект, чья карточка показывается</param> | |
/// <param name="propertySheet">Ссылка на интерфейс доступа к штатной карточке атрибутируемого объекта</param> | |
/// <remarks>Вызывается на клиентской стороне при использовании штатных карточек атрибутируемых объектов. | |
/// Исключения, вышедшие их этого метода, отправляются в серверный отчет об ошибке без показа сообщения пользователю.</remarks> | |
/// <remarks>Метод вызывается в порядке от шаблонов-родителей к детям-модификаторам </remarks> | |
public override void OnBeforeDisplayInUI( InfoObject obj, IPropertySheetCallback propertySheet ) | |
{ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment