Excel 上的 Pin 标题和第一行,如带有过滤器的表格

Posted

技术标签:

【中文标题】Excel 上的 Pin 标题和第一行,如带有过滤器的表格【英文标题】:Pin header and first row on Excel like table with filter 【发布时间】:2019-06-28 09:33:18 【问题描述】:

我有类似 Excel 的表格过滤器,我需要的是我想在向下滚动时固定标题和第一行。即使我应用过滤器,它也应该可以工作。

请注意小提琴:

http://jsfiddle.net/6ng3bz5c/1/

我尝试了以下方法但没有用:

$('tbody').scroll(function(e)  //detect a scroll event on the tbody
     $('tbody tr:nth-child(2)').css("down", $("tbody").scrollDown()); 
  );

前两个突出显示的行应保持向下滚动:

请指导我。

【问题讨论】:

【参考方案1】:

我建议您将position: sticky (mdn) 与first-of-type 结合使用来处理第一行(在我自己的项目中,我会使用类来设置这些样式,但我正在使用元素选择器以免更改你的标记)。

更多地了解您的 CSS,您还可以将第一行上的 top 偏移更改为更具响应性的东西,但为了演示,我只是使用了似乎对我有用的高度。您还需要添加边框。

thead th
  position:sticky;
  top:0;
  background:white;

tbody tr:first-of-type td
  position:sticky;
  top:34px;
  background:white;

var myApp = angular.module('myApp', [])
  .controller('employeeController', function($scope) 
    $scope.XLfilters =  list: [], dict: , results: [] ;
    $scope.markAll = function(field, b) 
      $scope.XLfilters.dict[field].list.forEach((x) => x.checked=b;);
    
    $scope.clearAll = function(field) 
      $scope.XLfilters.dict[field].searchText='';
      $scope.XLfilters.dict[field].list.forEach((x) => x.checked=true;);
    
    $scope.XLfiltrate = function() 
    	var i,j,k,selected,blocks,filter,option, data=$scope.XLfilters.all,filters=$scope.XLfilters.list;
      $scope.XLfilters.results=[];
      for (j=0; j<filters.length; j++) 
      	filter=filters[j];
        filter.regex = filter.searchText.length?new RegExp(filter.searchText, 'i'):false;
        for(k=0,selected=0;k<filter.list.length;k++)
        	if(!filter.list[k].checked)selected++;
          filter.list[k].visible=false;
          filter.list[k].match=filter.regex?filter.list[k].title.match(filter.regex):true;
        
        filter.isActive=filter.searchText.length>0||selected>0;
      
      for (i=0; i<data.length; i++)
        blocks=allows:[],rejects:[],mismatch:false;
      	for (j=0; j<filters.length; j++) 
          filter=filters[j]; option=filter.dict[data[i][filter.field]];
          (option.checked?blocks.allows:blocks.rejects).push(option);
          if(filter.regex && !option.match) blocks.mismatch=true;
      	
        if(blocks.rejects.length==1) blocks.rejects[0].visible=true;
        else if(blocks.rejects.length==0&&!blocks.mismatch)
          $scope.XLfilters.results.push(data[i]);
        	blocks.allows.forEach((x)=>x.visible=true);
        
      
      for (j=0; j<filters.length; j++) 
      	filter=filters[j];filter.options=[];
        for(k=0;k<filter.list.length;k++)
          if(filter.list[k].visible && filter.list[k].match) filter.options.push(filter.list[k]);
        
      
    
    function createXLfilters(arr, fields) 
      $scope.XLfilters.all = arr;
      for (var j=0; j<fields.length; j++) $scope.XLfilters.list.push($scope.XLfilters.dict[fields[j]]=list:[],dict:,field:fields[j],searchText:"",active:false,options:[]);
      for (var i=0,z; i<arr.length; i++) for (j=0; j<fields.length; j++) 
      z=$scope.XLfilters.dict[fields[j]];
      z.dict[arr[i][fields[j]]] || z.list.push(z.dict[arr[i][fields[j]]]=title:arr[i][fields[j]],checked:true, visible:false,match:false);
      
    

    createXLfilters(employees, ['Country','City']);
)

var employees = [
  "Name": "Manirul Monir",
  "City": "Sylhet",
  "Country": "Bangladesh"
, 
  "Name": "Arup",
  "City": "Sylhet",
  "Country": "Bangladesh"
, 
  "Name": "Person 1",
  "City": "Dhaka",
  "Country": "Bangladesh"
, 
  "Name": "Person 2",
  "City": "Dhaka",
  "Country": "Bangladesh"
, 
  "Name": "Munim Munna",
  "City": "Narshingdi",
  "Country": "Bangladesh"
, 
  "Name": "Mahfuz Ahmed",
  "City": "Narshingdi",
  "Country": "Bangladesh"
, 
  "Name": "Tawkir Ahmed",
  "City": "Gazipur",
  "Country": "Bangladesh"
, 
  "Name": "Alfreds 2",
  "City": "Berlin",
  "Country": "Germany"
, 
  "Name": "Alfreds Futterkiste",
  "City": "Berlin",
  "Country": "Germany"
, 
  "Name": "Blauer See Delikatessen",
  "City": "Mannheim",
  "Country": "Germany"
, 
  "Name": "Blondel père et fils",
  "City": "Strasbourg",
  "Country": "France"
, 
  "Name": "Bon app'",
  "City": "Marseille",
  "Country": "France"
, 
  "Name": "Centro comercial Moctezuma",
  "City": "México D.F.",
  "Country": "France"
];
.filterdropdown
  background: #eee;
  border: 1px solid #bbb;
  color: #bbb;
  border-radius: 2px;
  font-size: 14px;
  line-height: 14px;

.filterdropdown.active
  color: #005b9c;

a.filterlink
  font-size: 12px;

.options 
  height: 150px;
  overflow-y: scroll;

thead th
  position:sticky;
  top:0;
  background:white;

tbody tr:first-of-type td
  position:sticky;
  top:34px;
  background:white;
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div class="col-md-6" ng-app="myApp" ng-controller="employeeController">
  <table class="table table-bordered table-condensed" data="XLfiltrate()">
    <thead>
      <tr>
        <th>Country
          <div class="dropdown" style="float: right">
            <button class="dropdown-toggle filterdropdown" ng-class="active:XLfilters.dict['Country'].isActive" type="button" data-toggle="dropdown"><span class="glyphicon glyphicon-filter"></span></button>
            <div class="dropdown-menu prop" aria-labelledby="btnSearchBatch" style="width: 250px; padding: 15px;">
              <div class="text-right">
                <a href="#" class="filterlink" ng-click="clearAll('Country')">Clear All</a> | <a href="#" class="filterlink" data-dismiss="modal">Close(X)</a>
              </div>
              <form>
                <input type="text" class="form-control input-sm" ng-model="XLfilters.dict['Country'].searchText" placeholder="Filter by Country" />
                <div>
                  <a href="#" class="filterlink" ng-click="markAll('Country',true)">Select All</a> | <a href="#" class="filterlink" ng-click="markAll('Country',false)">Select None</a>
                </div>
                <div class="options">
                  <ul style="list-style-type: none; padding: 0">
                    <li ng-repeat="item in XLfilters.dict['Country'].options">
                      <input id="countryOption$index" type="checkbox" ng-model="XLfilters.dict['Country'].dict[item.title].checked" />&nbsp;<label for="countryOption$index">item.title</label>
                    </li>
                  </ul>
                </div>
              </form>
            </div>
          </div>
        </th>
        <th>City
          <div class="dropdown" style="float: right">
            <button class="dropdown-toggle filterdropdown" ng-class="active:XLfilters.dict['City'].isActive" type="button" data-toggle="dropdown"><span class="glyphicon glyphicon-filter"></span></button>
            <div class="dropdown-menu prop" aria-labelledby="btnSearchBatch" style="width: 250px; padding: 15px;">
              <div class="text-right">
                <a href="#" class="filterlink" ng-click="clearAll('City')">Clear All</a> | <a href="#" class="filterlink" data-dismiss="modal">Close(X)</a>
              </div>
              <form>
                <input type="text" class="form-control input-sm" ng-model="XLfilters.dict['City'].searchText" placeholder="Filter by City" />
                <div>
                  <a href="#" class="filterlink" ng-click="markAll('City',true)">Select All</a> | <a href="#" class="filterlink" ng-click="markAll('City',false)">Select None</a>
                </div>
                <div class="options">
                  <ul style="list-style-type: none; padding: 0">
                    <li ng-repeat="item in XLfilters.dict['City'].options">
                      <input id="cityOption$index" type="checkbox" ng-model="XLfilters.dict['City'].dict[item.title].checked" />&nbsp;<label for="cityOption$index">item.title</label>
                    </li>
                  </ul>
                </div>
              </form>
            </div>
          </div>
        </th>
        <th>Name</th>
      </tr>
    </thead>
    <tbody>
      <tr ng-repeat="emp in XLfilters.results">
        <td>emp.Country</td>
        <td>emp.City</td>
        <td>emp.Name</td>
      </tr>
    </tbody>
  </table>
</div>

【讨论】:

它会使标题保持不变,但我想让第一行也保持不变。请参考我在图片中突出显示的图片。 哎呀错过了;在我看来,first-of-type 在那里工作。查看更新的答案。 这可以在分页上实现吗?就像最初显示 10 条记录并显示所有值以进行相应的过滤和应用

以上是关于Excel 上的 Pin 标题和第一行,如带有过滤器的表格的主要内容,如果未能解决你的问题,请参考以下文章

怎样把EXCEL表格的第一行和第二行锁定?让它们不动。

如何使用 XlsxWriter 冻结第一行和第一列?

css让表格第一列和第一行固定

MySQL如何锁定一行及如何分析行锁定

刷新数据时的 SSAS (2008R2) 和 Excel 过滤器问题

只用scrapy获取一行输出到json文件