/// <summary> /// Configures a table cell. /// </summary> /// <typeparam name="TVal"></typeparam> /// <param name="expression">Cell property expression</param> /// <returns>Cell builder</returns> public MvcCoreBootstrapTableCellBuilder Cell <TVal>(Expression <Func <TVal> > expression) { string cellProperty = ((MemberExpression)expression.Body).Member.Name; CellConfig cellConfig = new CellConfig(); _configs.Add(cellProperty, cellConfig); return(_builderFactory.CellBuilder(cellConfig)); }
//------------------------------------------------------------------------- public CellApp() { Instance = this; Cfg = new CellConfig(); Rd = new ThreadSafeRandom(); jsonCfg = new JsonConfig(); // 注册BtFactory _regBtFactory(new BtFactoryBot()); _regBtFactory(new BtFactoryPlayer()); }
public CellConfig(float size) { instance = this; width = 2 * size; height = Mathf.Sqrt(3) * size; Vertices = new Vector3[6]; for (var i = 0; i < Vertices.Length; i++) { var angleDegree = 60 * i; var angleRadian = Mathf.Deg2Rad * angleDegree; Vertices[i] = new Vector3(size * Mathf.Cos(angleRadian), -0.5f, size * Mathf.Sin(angleRadian)); } }
private void Body(TableNode table) { TableNode body = this.CreateAndAppend("tbody", table); // Rows. foreach (RowConfig <T> rowConfig in _config.Rows) { TableNode row = this.CreateAndAppend("tr", body); this.AddContextualState(row.Element, rowConfig.State); this.AddCssClasses(row.Element, rowConfig.CssClasses); if (rowConfig.NavigationUrl != null) { row.Element.Attributes.Add("style", "cursor: pointer"); row.Element.Attributes.Add("onclick", $"window.location.href = '{rowConfig.NavigationUrl}'"); } else if (!string.IsNullOrEmpty(_config.RowClick) || !string.IsNullOrEmpty(rowConfig.RowClick)) { string jsCall = !string.IsNullOrEmpty(rowConfig.RowClick) ? rowConfig.RowClick : $"{_config.RowClick}(this)"; row.Element.Attributes.Add("style", "cursor: pointer"); row.Element.Attributes.Add("onclick", jsCall); } // Cells. this.IterateProperties(rowConfig.Entity, (property, _) => { CellConfig cellConfig = rowConfig.CellConfigs.ContainsKey(property.Name) ? rowConfig.CellConfigs[property.Name] : null; TableNode cell = this.CreateAndAppend("td", row); object cellValue = property.GetValue(rowConfig.Entity); cell.Element.InnerHtml.Append(cellValue?.ToString() ?? string.Empty); if (cellConfig != null) { this.AddContextualState(cell.Element, cellConfig.State); this.AddCssClasses(cell.Element, cellConfig.CssClasses); } }); } }
public void Cell() { CellBuilder configBuilder = new CellBuilder(null); CellConfig config = null; TableEntity entity = new TableEntity(); _builderFactory.CellBuilder(Arg.Do <CellConfig>(c => config = c)).Returns(configBuilder); CellBuilder builder = _builder.Cell(() => entity.Property); _builderFactory.Received(1).CellBuilder(Arg.Any <CellConfig>()); _configs.Should().HaveCount(1); _configs.Should().ContainKey("Property"); CellConfig cellConfig = _configs["Property"]; cellConfig.Should().BeSameAs(config); cellConfig.CssClasses.Should().BeEmpty(); cellConfig.State.Should().Be(ContextualState.Default); builder.Should().BeSameAs(configBuilder); }
/// <summary> /// 转换成工作簿 /// </summary> /// <typeparam name="T">实体</typeparam> /// <param name="source">数据源</param> /// <param name="excelFile">文件路径</param> /// <param name="sheetName">工作表名</param> /// <returns></returns> internal static IWorkbook ToWorkbook <T>(this IEnumerable <T> source, string excelFile, string sheetName) { // 静态属性还是实例属性 var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty); // 获取Fluent配置 bool fluentConfigEnabled = false; IFluentConfiguration fluentConfig; if (Excel.Setting.FluentConfigs.TryGetValue(typeof(T), out fluentConfig)) { fluentConfigEnabled = true; } // 获取单元格设置 var cellConfigs = new CellConfig[properties.Length]; for (var i = 0; i < properties.Length; i++) { PropertyConfiguration pc; var property = properties[i]; // 优先获取配置(高优先级),没有则获取属性 if (fluentConfigEnabled && fluentConfig.PropertyConfigs.TryGetValue(property, out pc)) { cellConfigs[i] = pc.CellConfig; } else { var attrs = property.GetCustomAttributes(typeof(NpoiColumnAttribute), true) as NpoiColumnAttribute[]; if (attrs != null && attrs.Length > 0) { cellConfigs[i] = attrs[0].CellConfig; } else { cellConfigs[i] = null; } } } // 初始化工作簿 var workbook = InitializeWorkbook(excelFile); // 创建工作表 var sheet = workbook.GetOrCreateSheet(sheetName); // 缓存单元格样式 var cellStyles = new Dictionary <int, ICellStyle>(); // 标题行单元格样式 var titleStyle = workbook.CreateCellStyle(); titleStyle.Alignment = HorizontalAlignment.Center; titleStyle.VerticalAlignment = VerticalAlignment.Center; //titleStyle.FillPattern=FillPattern.Bricks; titleStyle.FillBackgroundColor = HSSFColor.Grey40Percent.Index; titleStyle.FillForegroundColor = HSSFColor.White.Index; var titleRow = sheet.GetOrCreateRow(0); var rowIndex = 1; foreach (var item in source) { var row = sheet.GetOrCreateRow(rowIndex); for (int i = 0; i < properties.Length; i++) { var property = properties[i]; int index = i; var config = cellConfigs[i]; if (config != null) { if (config.IsIgnored) { continue; } index = config.Index; } // 首次 if (rowIndex == 1) { //如果没有标题,则使用属性名称作为标题 var title = property.Name; if (config != null) { if (!string.IsNullOrWhiteSpace(config.Title)) { title = config.Title; } if (!string.IsNullOrWhiteSpace(config.Formatter)) { try { var style = workbook.CreateCellStyle(); var dataFormat = workbook.CreateDataFormat(); style.DataFormat = dataFormat.GetFormat(config.Formatter); cellStyles[i] = style; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.ToString()); } } var titleCell = titleRow.GetOrCreateCell(index); titleCell.CellStyle = titleStyle; titleCell.SetCellValue(title); } } var value = property.GetValue(item, null); if (value == null) { continue; } var cell = row.GetOrCreateCell(index); ICellStyle cellStyle; if (cellStyles.TryGetValue(i, out cellStyle)) { cell.CellStyle = cellStyle; } var unwrapType = property.PropertyType.UnwrapNullableType(); cell.SetCellValueExt(value, unwrapType, config.CustomEnum, config.Formatter); } rowIndex++; } // 合并单元格 var mergableConfigs = cellConfigs.Where(c => c != null && c.AllowMerge).ToList(); if (mergableConfigs.Any()) { // 合并单元格样式 var vStyle = workbook.CreateCellStyle(); vStyle.VerticalAlignment = VerticalAlignment.Center; foreach (var config in mergableConfigs) { object previous = null; int rowspan = 0, row = 1; for (row = 1; row < rowIndex; row++) { var value = sheet.GetRow(row).GetCellValue(config.Index); if (object.Equals(previous, value) && value != null) { rowspan++; } else { if (rowspan > 1) { sheet.GetRow(row - rowspan).Cells[config.Index].CellStyle = vStyle; sheet.AddMergedRegion(new CellRangeAddress(row - rowspan, row - 1, config.Index, config.Index)); } rowspan = 1; previous = value; } } // 什么情况下——>所有行都需要合并 if (rowspan > 1) { sheet.GetRow(row - rowspan).Cells[config.Index].CellStyle = vStyle; sheet.MergeCell(row - rowspan, row - 1, config.Index, config.Index); } } } if (rowIndex > 1) { var statisticsConfigs = new List <StatisticsConfig>(); var filterConfigs = new List <FilterConfig>(); var freezeConfigs = new List <FreezeConfig>(); if (fluentConfigEnabled) { statisticsConfigs.AddRange(fluentConfig.StatisticsConfigs); filterConfigs.AddRange(fluentConfig.FilterConfigs); freezeConfigs.AddRange(fluentConfig.FreezeConfigs); } else { var statistics = typeof(T).GetCustomAttributes(typeof(NpoiStatisticsAttribute), true) as NpoiStatisticsAttribute[]; if (statistics != null && statistics.Length > 0) { foreach (var item in statistics) { statisticsConfigs.Add(item.StatisticsConfig); } } var freezes = typeof(T).GetCustomAttributes(typeof(NpoiFreezeAttribute), true) as NpoiFreezeAttribute[]; if (freezes != null && freezes.Length > 0) { foreach (var item in freezes) { freezeConfigs.Add(item.FreezeConfig); } } var filters = typeof(T).GetCustomAttributes(typeof(NpoiFilterAttribute), true) as NpoiFilterAttribute[]; if (filters != null && filters.Length > 0) { foreach (var item in filters) { filterConfigs.Add(item.FilterConfig); } } } // 统计行 foreach (var item in statisticsConfigs) { var lastRow = sheet.CreateRow(rowIndex); var cell = lastRow.CreateCell(0); cell.SetCellValue(item.Name); foreach (var column in item.Columns) { cell = lastRow.CreateCell(column); cell.CellFormula = $"{item.Formula}({GetCellPosition(1, column)}:{GetCellPosition(rowIndex - 1, column)})"; } rowIndex++; } // 设置冻结窗格 foreach (var item in freezeConfigs) { sheet.CreateFreezePane(item.ColSplit, item.RowSplit, item.LeftMostColumn, item.TopRow); } // 设置自动筛选 foreach (var item in filterConfigs) { sheet.SetAutoFilter(new CellRangeAddress(item.FirstRow, item.LastRow ?? rowIndex, item.FirstCol, item.LastCol)); } } // 自动调整所有列 for (int i = 0; i < properties.Length; i++) { sheet.AutoSizeColumn(i); } return(workbook); }
/// <summary> /// 初始化一个<see cref="NpoiColumnAttribute"/>类型的实例 /// </summary> public NpoiColumnAttribute() { CellConfig = new CellConfig(); }
private void UpdateBrushConfig() { _currentBrushCellConfig = _configsProvider.CellConfigProvider.GetConfig(_cellBrushType, _cellBrushSubType); }
internal CellBuilder(CellConfig config) { _config = config; }
/// <summary> /// 从指定Excel文件加载数据到<see cref="IEnumerable{T}"/>集合 /// </summary> /// <typeparam name="TEntity">实体类型</typeparam> /// <param name="excelFile">Excel文件</param> /// <param name="startRow">开始行</param> /// <param name="sheetIndex">工作表索引</param> /// <param name="valueConverter">单元格值转换器</param> /// <returns></returns> public static IEnumerable <TEntity> Load <TEntity>(string excelFile, int startRow = 1, int sheetIndex = 0, ValueConverter valueConverter = null) where TEntity : class, new() { if (!File.Exists(excelFile)) { throw new FileNotFoundException(); } var workbook = InitializeWorkbook(excelFile); // 目前,只处理一张(或使用foreach支持多张表) var sheet = workbook.GetSheetAt(sheetIndex); // 获取可写的属性 var properties = typeof(TEntity).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty); // 获取配置 bool fluentConfigEnabled = false; IFluentConfiguration fluentConfig; if (Setting.FluentConfigs.TryGetValue(typeof(TEntity), out fluentConfig)) { fluentConfigEnabled = true; } // 获取单元格设置 var cellConfigs = new CellConfig[properties.Length]; for (var i = 0; i < properties.Length; i++) { PropertyConfiguration pc; var property = properties[i]; // 优先获取配置(高优先级),没有则获取属性 if (fluentConfigEnabled && fluentConfig.PropertyConfigs.TryGetValue(property, out pc)) { cellConfigs[i] = pc.CellConfig; } else { var attrs = property.GetCustomAttributes(typeof(NpoiColumnAttribute), true) as NpoiColumnAttribute[]; if (attrs != null && attrs.Length > 0) { cellConfigs[i] = attrs[0].CellConfig; } else { cellConfigs[i] = null; } } } // 获取统计信息设置 var statistics = new List <StatisticsConfig>(); if (fluentConfigEnabled) { statistics.AddRange(fluentConfig.StatisticsConfigs); } else { var attrs = typeof(TEntity).GetCustomAttributes(typeof(NpoiStatisticsAttribute), true) as NpoiStatisticsAttribute[]; if (attrs != null && attrs.Length > 0) { foreach (var item in attrs) { statistics.Add(item.StatisticsConfig); } } } var list = new List <TEntity>(); int idx = 0; IRow headerRow = null; // 获取物理行 var rows = sheet.GetRowEnumerator(); while (rows.MoveNext()) { var row = rows.Current as IRow; if (idx == 0) { headerRow = row; } idx++; if (row.RowNum < startRow) { continue; } var item = new TEntity(); var itemIsValid = true; for (int i = 0; i < properties.Length; i++) { var prop = properties[i]; int index = i; var config = cellConfigs[i]; if (config != null) { index = config.Index; // 尝试从标题和缓存自动发现索引 if (index < 0 && config.AutoIndex && !string.IsNullOrWhiteSpace(config.Title)) { foreach (var cell in headerRow.Cells) { if (!string.IsNullOrWhiteSpace(cell.StringCellValue)) { if (cell.StringCellValue.Equals(config.Title, StringComparison.InvariantCultureIgnoreCase)) { index = cell.ColumnIndex; // 缓存 config.Index = index; break; } } } } // 再次检查 if (index < 0) { throw new ApplicationException("请通过 fluent api 或 属性 设置'index'或'autoIndex'"); } } var value = row.GetCellValue(index); if (valueConverter != null) { value = valueConverter(row.RowNum, index, value); } if (value == null) { continue; } // 检查是否统计行 if (idx > startRow + 1 && index == 0 && statistics.Any(s => s.Name.Equals(value.ToString(), StringComparison.InvariantCultureIgnoreCase))) { var st = statistics.FirstOrDefault( s => s.Name.Equals(value.ToString(), StringComparison.InvariantCultureIgnoreCase)); var formula = row.GetCellValue(st.Columns.First()).ToString(); if (formula.StartsWith(st.Formula, StringComparison.InvariantCultureIgnoreCase)) { itemIsValid = false; break; } } // 属性类型 var propType = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType; var safeValue = Convert.ChangeType(value, propType, CultureInfo.CurrentCulture); prop.SetValue(item, safeValue, null); } if (itemIsValid) { list.Add(item); } } return(list); }
public MvcCoreBootstrapTableCellBuilder CellBuilder(CellConfig config) { return(new MvcCoreBootstrapTableCellBuilder(config)); }
public CellBuilder CellBuilder(CellConfig config) { return(new CellBuilder(config)); }
internal MvcCoreBootstrapTableCellBuilder(CellConfig config) { _config = config; }
/// <summary> /// Initializes a new instance of the <see cref="PropertyConfiguration"/> class. /// </summary> public PropertyConfiguration() { CellConfig = new CellConfig(); }
private void Body(TableNode table) { TableNode body = this.CreateAndAppend("tbody", table); IList <RowConfig> rows = _config.Rows; if (!rows.Any()) { IQueryable <T> entities = _model.ProcessedEntities; if (!_model.Processed) { KeyValuePair <string, ColumnConfig> initialFilterColumn = _config.Columns .FirstOrDefault(c => c.Value.Filtering.Initial != null); KeyValuePair <string, ColumnConfig> initialSortColumn = _config.Columns .FirstOrDefault(c => c.Value.SortState.HasValue); // Initial rendering of the table, apply initial filteringm sorting and paging. if (initialFilterColumn.Key != null) { Expression <Func <T, bool> > whereExpr = ExpressionHelper.EqualsExpr <T>(initialFilterColumn.Key, initialFilterColumn.Value.Filtering.Initial); entities = entities.Where(whereExpr); } entities = _config.Paging.PageSize > 0 ? entities.Take(_config.Paging.PageSize) : entities; if (initialSortColumn.Key != null) { var sortExpr = ExpressionHelper.PropertyExpr <T>(initialSortColumn.Key); entities = initialSortColumn.Value.SortState == SortState.Ascending ? entities.OrderBy(sortExpr) : entities.OrderByDescending(sortExpr); } } // No row configuration has been performed. // Create rows from the entities. foreach (var row in entities.Select(e => new RowConfig(e))) { rows.Add(row); } } // Rows. foreach (RowConfig rowConfig in rows) { TableNode row = this.CreateAndAppend("tr", body); this.AddContextualState(row.Element, rowConfig.State, "table-"); this.AddCssClasses(rowConfig.CssClasses, row.Element); if (rowConfig.NavigationUrl != null) { row.Element.Attributes.Add("style", "cursor: pointer"); row.Element.Attributes.Add("onclick", $"window.location.href = '{rowConfig.NavigationUrl}'"); } else if (!string.IsNullOrEmpty(_config.RowClick) || !string.IsNullOrEmpty(rowConfig.RowClick)) { string jsCall = !string.IsNullOrEmpty(rowConfig.RowClick) ? rowConfig.RowClick : $"{_config.RowClick}(this)"; row.Element.Attributes.Add("style", "cursor: pointer"); row.Element.Attributes.Add("onclick", jsCall); } // Cells. this.IterateProperties(rowConfig.Entity, (property, columnConfig) => { CellConfig cellConfig = rowConfig.CellConfigs.ContainsKey(property.Name) ? rowConfig.CellConfigs[property.Name] : null; TableNode cell = this.CreateAndAppend("td", row); string cellValue = property.GetValue(rowConfig.Entity)?.ToString(); if (cellValue != null) { if (columnConfig != null && columnConfig.Filtering.Prepopulated && columnConfig.Filtering.Links) { TagBuilder filterLink = new TagBuilder("a"); filterLink.AddCssClass("FilterLink"); filterLink.InnerHtml.Append(cellValue?.ToString()); filterLink.Attributes.Add("href", "#"); this.SetupAjaxAttrs(filterLink, $"&filter[]={property.Name}&filter[]={cellValue}&filter[]={true}", property.Name); cell.Element.InnerHtml.AppendHtml(filterLink); } else { cell.Element.InnerHtml.Append(cellValue); } } if (cellConfig != null) { this.AddContextualState(cell.Element, cellConfig.State, "table-"); this.AddCssClasses(cellConfig.CssClasses, cell.Element); } }); } }
internal Cell(CellConfig config) { _config = config; }
/// <summary> /// Return instance of config prefab from pool /// </summary> /// <param name="config"></param> /// <returns></returns> public GameObject CreateFor(CellConfig config) { return(CreateFor(config.prefab)); }